diff options
| author | David Spruill <[email protected]> | 2026-07-20 16:40:01 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-07-20 16:40:01 -0400 |
| commit | 6b4e5cc14c3a45aa5c51badb6bfe4886af30ad32 (patch) | |
| tree | 296afa9bd3722816f2390bb5e9eff27c6e75eb93 | |
| parent | c5fc3ca1fd0e00a7e085ef48abfeff9c0c39817e (diff) | |
| parent | 15640356a5a6eeafefff403f6d287821213635cd (diff) | |
Merge branch 'develop' into user/daspr/kmodsamplefix
355 files changed, 62222 insertions, 3383 deletions
diff --git a/.github/Build-with-GitHub.md b/.github/Build-with-GitHub.md index c4a10962..cd1715ba 100644 --- a/.github/Build-with-GitHub.md +++ b/.github/Build-with-GitHub.md @@ -2,7 +2,7 @@ If you use GitHub to host your code, you can leverage [GitHub Actions](https://docs.github.com/en/actions) to create automated workflows to build your driver projects. -`windows-2022` runner (provided by `windows-latest`) is configured with Windows Driver Kit version 22H2 and Visual Studio 2022 off the box, so most solutions can be built by running `msbuild` directly. +`windows-2025-vs2026` runner is configured with Visual Studio 2026 off the box, so most solutions can be built by running `msbuild` directly using the WDK NuGet package. ```yaml name: Build driver solution @@ -16,7 +16,7 @@ jobs: matrix: configuration: [Debug, Release] platform: [x64] - runs-on: windows-2022 + runs-on: windows-2025-vs2026 env: Solution_Path: path\to\driver\solution.sln steps: diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index be83c18d..093db174 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,6 +10,8 @@ # Windows Implementation Library submodule /wil/ @microsoft/driver-samples-maintainers +# Samples + # Audio /audio/ @microsoft/windowsaudio diff --git a/.github/ISSUE_TEMPLATE/sample_issue.yml b/.github/ISSUE_TEMPLATE/sample_issue.yml new file mode 100644 index 00000000..4597086a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/sample_issue.yml @@ -0,0 +1,75 @@ +name: Issue with a sample +description: Report a problem you have with a specific sample. +title: '[path/to/sample]: ' +body: +- type: dropdown + id: sample_area + attributes: + label: Which is the area where the sample lives? + description: Select the area where you're experiencing the problem. + options: + - /TrEE/ + - /audio/ + - /avstream/ + - /bluetooth/ + - /filesys/cdfs/ + - /filesys/fastfat/ + - /filesys/miniFilter/ + - /general/DCHU/ + - /general/PLX9x5x/ + - /general/SimpleMediaSource/ + - /general/SystemDma/ + - /general/cancel/ + - /general/echo/ + - /general/event/ + - /general/ioctl/ + - /general/pcidrv/ + - /general/perfcounters/ + - /general/registry/ + - /general/toaster/ + - /general/tracing/ + - /gnss/ + - /gpio/ + - /hid/ + - /input/ + - /network/config/ + - /network/modem/ + - /network/ndis/ + - /network/radio/ + - /network/trans/ + - /network/wlan/ + - /network/wsk/ + - /network/wwan/ + - /nfc/ + - /pofx/PEP/ + - /pofx/UMDF2/ + - /pofx/WDF/ + - /pos/ + - /powerlimit/ + - /print/ + - /prm/ + - /sd/ + - /security/ + - /sensors/ + - /serial/ + - /setup/ + - /simbatt/ + - /smartcrd/ + - /spb/ + - /storage/ + - /thermal/ + - /tools/ + - /usb/ + - /video/ + - /wia/ + - /wmi/wmiacpi/ + - /wmi/wmisamp/ + validations: + required: true +- type: textarea + id: description + attributes: + label: Describe the issue + description: Provide a clear and concise description of what the issue is. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/sample_issue_generator.py b/.github/ISSUE_TEMPLATE/sample_issue_generator.py new file mode 100644 index 00000000..4b6eee64 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/sample_issue_generator.py @@ -0,0 +1,72 @@ +import yaml +import os + +# Read the CODEOWNERS file +codeowners_path = os.path.join(os.path.dirname(__file__), "..", "CODEOWNERS") +with open(codeowners_path, "r") as file: + lines = file.readlines() + +# Parse the CODEOWNERS file to extract areas and their paths +areas = [] +sample_section_found = False + +for line in lines: + line = line.strip() + if line.startswith("# Samples"): + sample_section_found = True + continue + + if sample_section_found: + if line.startswith("#"): + continue + elif line: + path, codeowner = line.split() + if path in areas: + raise ValueError(f"Path:{path} has been found two times inside CODEOWNERS file") + areas.append(path) + + +# Sort the areas in lexicographical order +areas = sorted(areas) + +# Generate the YAML structure +yaml_form = { + "name": "Issue with a sample", + "description": "Report a problem you have with a specific sample.", + "title": "[path/to/sample]: ", + "body": [] +} + +dropdown = { + "type": "dropdown", + "id": "sample_area", + "attributes": { + "label": "Which is the area where the sample lives?", + "description": "Select the area where you're experiencing the problem.", + "options": areas + }, + "validations": { + "required": True + } +} + +# Add a description field +description_field = { + "type": "textarea", + "id": "description", + "attributes": { + "label": "Describe the issue", + "description": "Provide a clear and concise description of what the issue is." + }, + "validations": { + "required": True + } +} + +yaml_form["body"].append(dropdown) +yaml_form["body"].append(description_field) + +# Write the YAML to a file +output_path = os.path.join(os.path.dirname(__file__), "sample_issue.yml") +with open(output_path, "w") as outfile: + yaml.dump(yaml_form, outfile, sort_keys=False) diff --git a/.github/crashdetect/CrashDetectCreateUsb.cmd b/.github/crashdetect/CrashDetectCreateUsb.cmd new file mode 100644 index 00000000..571f0393 --- /dev/null +++ b/.github/crashdetect/CrashDetectCreateUsb.cmd @@ -0,0 +1,189 @@ +@echo off +setlocal + +set WINPE_DRIVE=A +set WINUSB_DRIVE=B +set EXITCODE=0 + +rem Pre-check +if not exist "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\DISM\dism.exe" ( + echo ERROR: Missing DISM tool! + goto error +) +if not exist "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\en-us\winpe.wim" ( + echo ERROR: Missing winpe.wim image! + goto error +) +if not exist "C:\WinPE_USB\Scripts\CrashDetectOsReinstall.cmd" ( + echo ERROR: Missing script C:\WinPE_USB\Scripts\CrashDetectOsReinstall.cmd! + goto error +) +if not exist "C:\WinPE_USB\Scripts\Unattend.xml" ( + echo ERROR: Missing XML C:\WinPE_USB\Scripts\Unattend.xml! + goto error +) +if not exist "C:\WinPE_USB\Images\install.wim" ( + echo ERROR: Missing WIM C:\WinPE_USB\Images\install.wim! + goto error +) + +rem Environment setup. +echo Setting up environment for ADK tools... +cd "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools>" +call DandISetEnv.bat +echo Done setting up environment. + +rem Ask for the USB disk number displayed in Diskpart. +echo Displaying detected disk drives.. +echo Creating DiskPart script... +( +echo list disk +) > C:\WinPE_USB\diskpart.txt +diskpart /s C:\WinPE_USB\diskpart.txt +del C:\WinPE_USB\diskpart.txt +echo( +echo( +echo Note that Disk 0 is often the OS drive you do NOT want to format! +echo( +echo Ensure drive letters %WINPE_DRIVE%: and %WINUSB_DRIVE%: are not currently assigned to other drives! +echo It's ok if it's assigned to the target USB. +echo( +set /p USBDISK=Enter the Disk Number of the USB drive you want to make WinPE bootable: +echo( +echo Disk %USBDISK% selected. + +rem Create a USB drive with WinPE and data partitions. +echo( +echo WARNING!!!: VERIFY DISK %USBDISK% IS THE CORRECT USB DISK TO FORMAT! +choice /C YN /M "ARE YOU SURE YOU WANT TO FORMAT DISK %USBDISK%?" +echo( +if %errorlevel% equ 2 ( + echo You chose NO, exiting without modifying USB key. + exit /b 0 +) +if %errorlevel% equ 1 ( + echo You chose YES, proceeding with formatting USB key. +) + +:dism +rem Update startnet.cmd autorun script in WinPE boot image (winpe.wim). +cd /d "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64" +echo( +if not exist "C:\WinPE_USB\WinPE_amd64\mount" ( + echo Creating temp folders C:\WinPE_USB\WinPE_amd64\mount... + mkdir "C:\WinPE_USB\WinPE_amd64\mount" +) +echo Mounting WinPE image to modify... +Dism /Mount-Image /ImageFile:"en-us\winpe.wim" /index:1 /MountDir:"C:\WinPE_USB\WinPE_amd64\mount" +if errorlevel 1 ( + echo ERROR: DISM failed to mount ImageFile:"en-us\winpe.wim"! + goto error +) +echo Done mounting winpe.wim image. +echo Updating startnet.cmd autorun script in WinPE boot image... +( +echo wpeinit +echo. +echo @echo off +echo rem Find USB drive. +echo for %%%%D in (D E F G H I J K L M N O P Q R S T U V W Y Z^) do ^( +echo if exist %%%%D:Scripts\CrashDetectOsReinstall.cmd ^( +echo call %%%%D:Scripts\CrashDetectOsReinstall.cmd +echo goto EOF +echo ^) +echo ^) +) > "C:\WinPE_USB\WinPE_amd64\mount\Windows\System32\startnet.cmd" +echo Done adding CrashDetectOsReinstall.cmd to startnet.cmd. +echo Unmounting WinPE image with committed changes... +Dism /Unmount-Image /MountDir:"C:\WinPE_USB\WinPE_amd64\mount" /commit +if errorlevel 1 ( + echo ERROR: DISM failed to unmount ImageFile:"en-us\winpe.wim"! + echo USB drive have not been touched yet. + goto error +) +echo Done unmounting winpe.wim image. + +rem Delete temp "WinPE_amd64" folder, else the "copype.cmd" below will fail if the folder is already present. +rmdir /s /q "C:\WinPE_USB\WinPE_amd64" +echo Deleted temp folder "C:\WinPE_USB\WinPE_amd64". +echo( +echo Wiping out USB and creating 2 partitions... +echo Creating DiskPart script... +( +echo select disk %USBDISK% +echo clean +echo create partition primary size=2048 +echo active +echo format fs=FAT32 quick label="WinPE" +echo assign letter=%WINPE_DRIVE% +echo create partition primary +echo format fs=NTFS quick label="WinUSB" +echo assign letter=%WINUSB_DRIVE% +) > C:\WinPE_USB\diskpart.txt +echo Partitioning USB... +diskpart /s C:\WinPE_USB\diskpart.txt +if errorlevel 1 ( + echo ERROR: DiskPart failed during partitioning and formatting USB! + del C:\WinPE_USB\diskpart.txt + goto error +) +del C:\WinPE_USB\diskpart.txt +echo Done partitioning and formatting USB. +echo( +rem The "copype.cmd" script will create working directory "WinPE_amd64", it will fail if directory already exist. +echo Copying WinPE working files to "C:\WinPE_USB\WinPE_amd64"... +call copype.cmd amd64 "C:\WinPE_USB\WinPE_amd64" +if errorlevel 1 ( + echo ERROR: Script "copype.cmd" failed to copy working files! + goto error +) +echo Done copying WinPE files. +echo( +rem Install WinPE to the USB and make it bootable. +echo Creating bootable WinPE USB... +call Makewinpemedia.cmd /ufd /f "C:\WinPE_USB\WinPE_amd64" "%WINPE_DRIVE%:" /bootex +if errorlevel 1 ( + echo ERROR: Script "Makewinpemedia.cmd" failed to make WinPE USB bootable! + goto error +) +echo Done, WinPE USB drive is now bootable. +echo( +rem Copy Unattend.xml, scripts and install.wim over to USB +echo Copying Unattend.xml and scripts over to USB... +xcopy "C:\WinPE_USB\Scripts\" "%WINUSB_DRIVE%:\Scripts\" /E /I /R /Y +if errorlevel 1 ( + echo ERROR: Failed copying scripts from "C:\WinPE_USB\Scripts\" to USB! + goto error +) +echo Done copying script files. +echo( +echo Copying install.wim over to USB...this could take a while... +robocopy "C:\WinPE_USB\Images" "%WINUSB_DRIVE%:\Images" install.wim /ETA /J +if %errorlevel% geq 8 ( + echo ERROR: Failed copying install.wim from "C:\WinPE_USB\Images\" to USB! + goto error +) +echo Done copying WIM file. +echo( +goto cleanup + +:error +set EXITCODE=1 +goto cleanup + +:cleanup +rem Clean up any temp folders. +if exist "C:\WinPE_USB\WinPE_amd64" ( + rmdir /s /q "C:\WinPE_USB\WinPE_amd64" + echo Cleaned up temp folder "C:\WinPE_USB\WinPE_amd64". +) + +:done +if %EXITCODE% equ 0 ( + echo( + echo SUCCESSFULLY CREATED BOOTABLE WINPE USB DRIVE. +) else ( + echo( + echo FAILED CREATING BOOTABLE WINPE USB DRIVE! +) +endlocal & exit /b %EXITCODE%
\ No newline at end of file diff --git a/.github/crashdetect/CrashDetectOsReinstall.cmd b/.github/crashdetect/CrashDetectOsReinstall.cmd new file mode 100644 index 00000000..faebb443 --- /dev/null +++ b/.github/crashdetect/CrashDetectOsReinstall.cmd @@ -0,0 +1,258 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +echo CrashDetectOsReinstall.cmd...START + +echo Searching for the USB drive volume letter... +set "USB=" + +for %%D in (D E F G H I J K L M N O P Q R S T U V W Y Z) do ( + if exist "%%D:\Scripts\CrashDetectOsReinstall.cmd" ( + set "USB=%%D" + echo Found USB at drive volume letter !USB!: + ) +) + +if not defined USB ( + echo ERROR: Did not find USB drive volume letter + goto error +) + +if not exist "!USB!:\Logs" ( + echo Creating Logs directory on USB + mkdir "!USB!:\Logs" +) +set "LOG=!USB!:\Logs\CrashDetectOsReinstall.log" +echo Created log file "%LOG%" on USB +echo [%DATE% %TIME%] CrashDetectOsReinstall.cmd...START >> "%LOG%" +echo [%DATE% %TIME%] Found USB at drive volume letter !USB!: >> "%LOG%" + +set "FLAG_RETRIES=!USB!:\Logs\Retries.flg" +set "FLAG_INSTALLOS=!USB!:\Logs\InstallOs.flg" +set "FLAG_DEPLOYOSDONE=!USB!:\Logs\DeployOsDone.flg" + + +:installos +if exist "%FLAG_INSTALLOS%" ( + if exist "%FLAG_DEPLOYOSDONE%" ( + echo OS reinstall done. + echo [%DATE% %TIME%] OS reinstall done. >> "%LOG%" + del "%FLAG_INSTALLOS%" >> "%LOG%" 2>&1 + del "%FLAG_DEPLOYOSDONE%" >> "%LOG%" 2>&1 + goto reboot + ) + echo Reinstalling OS... + echo [%DATE% %TIME%] Reinstalling OS... >> "%LOG%" + goto deployos +) + + +:detectcrash +if exist "C:\Windows\Minidump\" ( + echo OS crashed on last reboot into the OS! + echo [%date% %time%] OS crashed on last reboot into the OS! >> "%LOG%" + + set "MININAME=" + for %%F in ("C:\Windows\Minidump\*.dmp") do ( + set "MININAME=%%~nF" + echo Minidump filename: !MININAME! >> "%LOG%" + ) + + echo Backing up Minidump files... + copy /y "C:\Windows\Minidump\*.dmp" "!USB!:\Logs" >> "%LOG%" 2>&1 + if !errorlevel! neq 0 ( + echo ERROR: Failed to back up Mini dump file + echo [%date% %time%] ERROR: Failed to back up Mini dump file >> "%LOG%" + ) + rmdir /s /q "C:\Windows\Minidump" >> "%LOG%" 2>&1 + if !errorlevel! neq 0 ( + echo ERROR: Failed to delete Minidump folder + echo [%date% %time%] Failed to delete Minidump folder >> "%LOG%" + ) + + if exist "C:\Windows\MEMORY.DMP" ( + if defined MININAME ( + ren "C:\Windows\MEMORY.DMP" "MEMORY-!MININAME!.DMP" >> "%LOG%" 2>&1 + ) + if !errorlevel! neq 0 ( + echo ERROR: Failed to rename MEMORY.DMP file + echo [%date% %time%] ERROR: Failed to rename MEMORY.DMP file >> "%LOG%" + echo Backing up MEMORY.DMP file... + copy /y "C:\Windows\MEMORY.DMP" "!USB!:\Logs" >> "%LOG%" 2>&1 + ) else ( + echo Backing up MEMORY-!MININAME!.DMP file... + copy /y "C:\Windows\MEMORY-!MININAME!.DMP" "!USB!:\Logs" >> "%LOG%" 2>&1 + ) + if !errorlevel! neq 0 ( + echo ERROR: Failed to back up MEMORY.DMP file + echo [%date% %time%] ERROR: Failed to back up MEMORY.DMP file >> "%LOG%" + ) + ) + + echo Done trying to back up files to USB + echo [%date% %time%] Done trying to back up files to USB >> "%LOG%" + goto retry +) else ( + rem If OS crashed just now, it will be detected on next reboot. + rem Minidump folder used for crash detection is not created yet on automatic first crash reboot until OS is loaded. + echo No OS crash on last reboot into the OS. + echo [%date% %time%] No OS crash on last reboot into the OS. >> "%LOG%" + if exist %FLAG_RETRIES% ( + del %FLAG_RETRIES% >> "%LOG%" 2>&1 + ) + goto reboot +) + + +:retry +set "TRIES=0" +rem Retries are always one less than actual crashes because first crash is not detected. +set "MAX_RETRIES=2" + +if not exist "%FLAG_RETRIES%" ( + echo Creating "%FLAG_RETRIES%" with default retries set to 0 >> "%LOG%" + echo RETRIES=0 > "%FLAG_RETRIES%" +) + +for /f "tokens=1,2 delims==" %%A in (%FLAG_RETRIES%) do ( + if /i "%%A"=="RETRIES" ( + set "TRIES=%%B" >> "%LOG%" 2>&1 + ) +) + +set /a TRIES+=0 2>nul >> "%LOG%" 2>&1 +set /a TRIES+=1 >> "%LOG%" 2>&1 +echo RETRIES=!TRIES! > %FLAG_RETRIES% + +echo Current OS boot retries: !TRIES! +echo Current OS boot retries: !TRIES! >> "%LOG%" +if !TRIES! GEQ %MAX_RETRIES% ( + echo Max %MAX_RETRIES% retries reached, reinstalling OS... + del %FLAG_RETRIES% >> "%LOG%" 2>&1 + type nul > %FLAG_INSTALLOS% + goto installos +) else ( + echo Max %MAX_RETRIES% retries allowed, booting into OS... + goto reboot +) + + +:deployos +rem Image index is the OS edition to install from a multi-edition OS install image. +rem For "Windows 11 25H2" image, "Windows 11 Pro" is the 6th item on the list of editions available. +rem Adjust accordingly to install other OS editions. +rem For single edition OS images, set index to 1. +set "IMAGE_INDEX=6" +set "TARGET_DISK=0" +set "SYSTEM_DRIVE=S" +set "SYSTEM_LABEL=System" +set "TARGET_DRIVE=W" +set "TARGET_LABEL=TestOS" +set "INSTALL_WIM=install.wim" +set "UNATTEND_XML=Unattend.xml" + +echo Setting flag InstallOs.flg for CrashDetectOsReinstall.cmd autorun script to detect OS install. >> "%LOG%" +type nul > "%FLAG_INSTALLOS%" + +echo [1/8] Creating DiskPart script... +echo [%DATE% %TIME%] [1/8] Creating DiskPart script... >> "%LOG%" +( +echo select disk "%TARGET_DISK%" +echo clean +echo convert gpt +echo create partition efi size=100 +echo format quick fs=fat32 label="%SYSTEM_LABEL%" +echo assign letter="%SYSTEM_DRIVE%" +echo create partition msr size=16 +echo create partition primary +echo format quick fs=ntfs label="%TARGET_LABEL%" +echo assign letter="%TARGET_DRIVE%" +) > X:\diskpart.txt + +echo [2/8] Partitioning target disk... +echo [%DATE% %TIME%] [2/8] Partitioning target disk... >> "%LOG%" +diskpart /s X:\diskpart.txt >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: DiskPart failed. See %LOG% + goto error +) + +echo [3/8] Applying OS WIM image... +echo [%DATE% %TIME%] [3/8] Applying image... >> "%LOG%" +dism /Apply-Image /ImageFile:"!USB!:\Images\%INSTALL_WIM%" /Index:"%IMAGE_INDEX%" /ApplyDir:"%TARGET_DRIVE%":\ >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: DISM apply failed. See %LOG% + goto error +) + +echo [4/8] Copying "%UNATTEND_XML%"... +echo [%DATE% %TIME%] [4/8] Copying %UNATTEND_XML%... >> "%LOG%" +if not exist "%TARGET_DRIVE%:\Windows\Panther" ( + mkdir "%TARGET_DRIVE%:\Windows\Panther" >> "%LOG%" 2>&1 +) +copy /y "!USB!:\Scripts\%UNATTEND_XML%" "%TARGET_DRIVE%:\Windows\Panther\%UNATTEND_XML%" >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: Failed to copy %UNATTEND_XML%. See %LOG% + echo [%DATE% %TIME%] ERROR: Failed to copy %UNATTEND_XML%. >> %LOG% + goto error +) + +echo [5/8] Creating boot files... +echo [%DATE% %TIME%] [5/8] Creating boot files... >> "%LOG%" +bcdboot W:\Windows /s S: /f UEFI >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: BCDBOOT failed. See %LOG% + goto error +) + +echo [6/8] Setting one-time bootsequence to OS boot manager... +echo [%DATE% %TIME%] [6/8] Setting one-time bootsequence to OS boot manager... >> "%LOG%" +bcdedit /set {fwbootmgr} bootsequence {bootmgr} +echo bcdedit /set {fwbootmgr} bootsequence {bootmgr} >> "%LOG%" +if errorlevel 1 ( + echo ERROR: BCDEDIT /set {fwbootmgr} bootsequence {bootmgr} failed. See "%LOG%" + goto error +) + +echo [7/8] Deployment complete. +echo [%DATE% %TIME%] [7/8] Deployment complete. >> "%LOG%" +echo Deployment complete. >> "%LOG%" +echo Setting flag DeployOsDone.flg for script to detect OS install complete and boot into OS. +type nul > "%FLAG_DEPLOYOSDONE%" + +echo [8/8] Rebooting into OS in 10sec... +echo [%DATE% %TIME%] [8/8] Rebooting into OS in 10sec... >> "%LOG%" +rem Simulate timeout with ping (10 sec) +ping -n 11 127.0.0.1 >nul +wpeutil reboot >> "%LOG%" 2>&1 + + +:reboot +echo Rebooting into OS in 10sec... +echo [%DATE% %TIME%] Rebooting into OS... >> "%LOG%" +rem Force next boot into Windows boot manager. +bcdedit /set {fwbootmgr} bootsequence {bootmgr} >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: BCDEDIT /set {fwbootmgr} bootsequence {bootmgr} - failed. See "%LOG%" + goto error +) +rem Disable WinRE prompt to attempt system recovery, which requires user intervention. +bcdedit /set {default} recoveryenabled no >> "%LOG%" 2>&1 +if errorlevel 1 ( + echo ERROR: BCDEDIT /set {default} recoveryenabled no - failed. See "%LOG%" +) +rem Simulate timeout with ping (10 sec) +ping -n 11 127.0.0.1 >nul +wpeutil reboot >> "%LOG%" 2>&1 + + +:error +echo CrashDetectOsReinstall.cmd...ERROR! See "%LOG%" +echo [%DATE% %TIME%] CrashDetectOsReinstall.cmd...ERROR! >> "%LOG%" +exit /b 1 >> "%LOG%" 2>&1 + + +:done +echo CrashDetectOsReinstall.cmd...DONE! +echo [%DATE% %TIME%] CrashDetectOsReinstall.cmd...DONE! >> "%LOG%" +exit /b 0 >> "%LOG%" 2>&1 diff --git a/.github/crashdetect/CrashDetectSetupGuide.md b/.github/crashdetect/CrashDetectSetupGuide.md new file mode 100644 index 00000000..dc974507 --- /dev/null +++ b/.github/crashdetect/CrashDetectSetupGuide.md @@ -0,0 +1,256 @@ +# Crash Detect USB Setup Guide: <br>Automating Crash Detection and OS Reinstall of Target Test Systems + +--- + +## A) Overview +This guide walks through setting up a new bootable WinPE USB drive using: + +- A **Host Controller** (to build the USB) +- A **bootable WinPE USB** (automatic crash detection and OS reinstall) +- A **target test system** + +### High-level flow +1. Download Windows image (ISO) +2. Install Windows ADK + WinPE add-on +3. Create bootable WinPE USB +4. Copy image + scripts to USB +5. Boot up target system +6. OPTIONAL: Install OS on new Target System +7. OPTIONAL: Add a Custom Script to Windows Setup + +--- + +## B) Requirements + +### Host Controller +- Windows 11 25H2 +- Administrator privileges +- USB drive (>= 64GB recommended) +- Internet connection + +### Target System +- Windows 11 25H2 +- BIOS boot priority set to **USB boot** and **Secure Boot disabled** +- Windows System failure recovery set to **"Automatically restart"** +- Willing to wipe disk (automatic OS reinstall from crash) + +--- + +## C) Download Required Software and Scripts onto the Host Controller + +### Windows OS Image (ISO) +- [Download Windows 11 (official)](https://www.microsoft.com/en-us/software-download/windows11) +- Go to section "Download Windows 11 Disk Image (ISO) for x64 devices". +- Select the option "Windows 11 (multi-edition ISO for x64 devices)". +- Click "Confirm" button. +- Section "Select the product language" should appear. +- Select your language option. (Ex: "English (United States)") +- Click "Confirm" button. +- Section "Download - Windows 11 English" should appear. +- Click "64-bit Download" button. + +Mount ISO: +- In File Explorer, go to the location you downloaded the ISO file `Win11_25H2_English_x64_v2.iso` to. +- Right-click on the ISO file and select "Mount". + - If the "Open File - Security Warning" prompt pops up after a minute then click "Open". + - (The prompt may be hidden behind other Windows.) +- Create new folder and subfolder `C:\WinPE_USB\Images`. +- Go to the `%MountDriveLetter%:\sources` folder and copy the **`install.wim`** file to **`C:\WinPE_USB\Images`**. + - This is the Windows 11 OS image file that the DISM tool will need to deploy the OS. + - This file will be copied over to the USB later after bootable WinPE USB creation. +- Right-click on the %MountDriveLetter% and select "Eject" to unmount the ISO image. + +--- + +### Windows Assessment and Deployment Kit (Deployment Tools) & Windows PE Add-on +- [Download Windows ADK & WinPE Add-on](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install) +- Go to section "Download the ADK 10.1.26100.2454 (December 2024)". +- Click on the link "Download the Windows ADK 10.1.26100.2454 (December 2024)" to download the `adksetup.exe` installer. +- Click on the link "Download the Windows PE add-on for the Windows ADK 10.1.26100.2454 (December 2024)" to download the `adkwinpesetup.exe` installer. + +Install ADK: +- Double-click on the `adksetup.exe` from the location you downloaded the file to launch the installer. +- "Specify Location" page, click "Next", to install at default location. +- "Windows Kits Privacy" page, select your privacy option, click "Next". +- "License Agreement" page, click "Accept". +- "Select the features you want to install" page, confirm "Deployment Tools" is checked, then click "Install". +- If "User Account Control" prompt appears, click "Yes" to begin installation process. +- "Installing features..." page, wait for installation process to complete. +- "Welcome to the Windows Assessment and Deployment Kit!" page, click "Close". + +Install WinPE Add-on: <br>**Important:** Install **ADK first**, then WinPE add-on +- Double-click on the `adkwinpesetup.exe` from the location you downloaded the file to launch the installer. +- "Specify Location" page, click "Next", to install at default location. +- "Windows Kits Privacy" page, select your privacy option, click "Next". +- "License Agreement" page, click "Accept". +- "Select the features you want to install" page, confirm "Windows Preinstallation Environment (Windows PE)" is checked, then click "Install". +- If "User Account Control" prompt appears, click "Yes" to begin installation process. +- "Installing features..." page, wait for installation process to complete. +- "Welcome to the Windows Assessment and Deployment Kit Windows Preinstallation Environment Add-ons!" page, click "Close". + +--- + +### Unattend and Script Files from GitHub +- Download files from [Windows-driver-samples/tree/main/.github/crashdetect](https://github.com/microsoft/Windows-driver-samples/tree/main/.github/crashdetect) +- Create directory **`C:\WinPE_USB\Scripts\`** and copy the following downloaded files to there. + - `CrashDetectCreateUsb.cmd` + - `CrashDetectOsReinstall.cmd` + - `Unattend.xml` + +--- + +## D) Create Bootable WinPE USB +- **TIP:** It's a good idea to make a backup copy of the original **"winpe.wim"** image file before editing it in the following steps. + - `C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\en-us\winpe.wim` + +- Plug a USB drive into the Host Controller. +- Check to make sure drive letters **A:** and **B:** are not currently used by any other drive. If used by the target USB drive, it's okay. +- Confirm the folder **`C:\WinPE_USB`** and its subfolders **`Scripts`** and **`Images`** exist. +- Confirm the **`Scripts`** subfolder contains the following files that were downloaded from previous steps. + - `CrashDetectOsReinstall.cmd` + - `Unattend.xml` +- Confirm the **`Images`** subfolder contains the Win11 OS image file. + - `install.wim` + +### OPTION 1: Use the `CrashDetectCreateUsb.cmd` script to create the USB automatically. +- Start a `Command Prompt` running as administrator. +- Run the script by typing the following line into the Command Prompt. +```cmd +C:\WinPE_USB\Scripts\CrashDetectCreateUsb.cmd +``` +- The script will display a list of detected disk drives, usually Disk 0 is the OS disk, DO NOT select that disk. +- Prompt 1: will ask you to enter the Disk number of your USB drive. +- Prompt 2: will ask you to confirm one last time before wiping out the USB drive. +- The last step will copy over the `install.wim` OS image to the USB, which could take a while. + +### OPTION 2: Follow the steps below to create the USB manually. +#### 1. Make sure your PC has the ADK and ADK Windows PE add-on installed. + - Start the `Deployment and Imaging Tools Environment` running as administrator. + +#### 2. Update the `startnet.cmd` autorun script in the WinPE boot image. + - Mount the WinPE boot image (`winpe.wim`) using DISM. + - Adds the `CrashDetectOsReinstall.cmd` script to the `startnet.cmd` script. +```cmd +( +echo wpeinit +echo. +echo @echo off +echo REM Find USB drive. +echo for %%D in (D E F G H I J K L M N O P Q R S T U V W Y Z^) do ^( +echo if exist %%D:Scripts\CrashDetectOsReinstall.cmd ^( +echo call %%D:Scripts\CrashDetectOsReinstall.cmd +echo goto EOF +echo ^) +echo ^) +) > "C:\WinPE_USB\WinPE_amd64\mount\Windows\System32\startnet.cmd" +``` + - Unmount the WinPE image using DISM. +```cmd +Dism /Unmount-Image /MountDir:"C:\WinPE_USB\WinPE_amd64\mount" /commit +``` + - Delete folder `C:\WinPE_USB\WinPE_amd64`, else the `copype.cmd` below will fail if the folder is already present. +```cmd +rmdir /s /q "C:\WinPE_USB\WinPE_amd64" +``` + +#### 3. Create and format a multiple partition USB drive. + - Attach a USB large enough for 2GB WinPE partition + WinUSB partition (Win11 WIM 8GB + Memory dump files 16GB-64GB + Scripts). + - Enter the following commands into the command prompt. +```cmd +diskpart +list disk +select disk X (where X is your USB drive) +clean +create partition primary size=2048 +active +format fs=FAT32 quick label="WinPE" +assign letter=A +create partition primary +format fs=NTFS quick label="WinUSB" +assign letter=B +exit +``` + +#### 4. Create a bootable Windows PE USB drive. + - Copying WinPE boot files to a working directory. +```cmd +copype.cmd amd64 "C:\WinPE_USB\WinPE_amd64" +``` + - Copy the WinPE files to the WinPE partition on USB. +```cmd +MakeWinPEMedia.cmd /UFD /F "C:\WinPE_USB\WinPE_amd64" "A:" /bootex +``` + +--- + +#### 5. Copy scripts and OS install image over to WinUSB partition on USB. + - Copy Script files over to USB. +```cmd +xcopy "C:\WinPE_USB\Scripts\" "B:\Scripts\" /E /I /R /Y +``` + - Copy Windows 11 OS WIM file over to USB, this could take a while... +```cmd +robocopy "C:\WinPE_USB\Images" "B:\Images" install.wim /ETA /J +``` + +--- + +## E) Boot Up Target System +- Insert USB into target PC +- Power on +- Enter boot menu (F12 / ESC / DEL depending on vendor) +- Confirm BIOS/UEFI setting has USB Drive as the first boot priority. (Varies among vendors) +- Confirm Secure Boot setting is Disabled +- Save BIOS settings to reboot target system. +- WinPE will automatically launch the "startnet.cmd" script we edited earlier in the "winpe.wim" image. +- The script will call "wpeinit", then our "CrashDetectOsReinstall.cmd" script to begin automatic OS crash detection and reimage for WDK driver testing. + +--- + +## F) OPTIONAL: Install OS on new Target System +### On the bootable USB's second partition `WinPE_USB` +- Create the folder **`Logs`**. +- Create an empty file **`InstallOs.flg`** in that folder. + - (In File Explorer, ensure file name extensions are visible, else the filename may be accidentally set to `InstallOs.flg.txt`) +- Plug USB into target system and reboot into USB. +- The USB will detect the flag and begin reinstalling the OS immediately. + - **WARNING**: There will be **NO** prompt to reconfirm OS install, be sure to plug into the correct target system. + - Do **NOT** leave this USB plugged into the Host Controller when this flag is set, to avoid accidental OS reinstall. + +--- + +## G) OPTIONAL: Add a Custom Script to Windows Setup +### Setupcomplete.cmd and ErrorHandler.cmd +- These are custom scripts that run during or after the Windows Setup process. They can be used to install applications or run other tasks by using cscript/wscript scripts. +- Follow instructions on this website: + - (https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/add-a-custom-script-to-windows-setup) + +--- + +## Troubleshooting +### ERROR: Script "Makewinpemedia.cmd" failed to make WinPE USB bootable! +- If your Host Controller is connected to a secured IT network, the actions in this script may have been blocked. +- Check to see if **"bootsect.exe"** was blocked by Windows Security. + - Run "Windows Security" + - Select "Virus & threat protection" + - Click link "Manage ransomware protection" at the bottom + - Click link "Allow an app through Controlled folder access" + - Click button "Add an allowed app" button, then select option "Recently blocked apps" + - Scroll down and look for the "bootsect.exe" app to add to allow list +### USB won't boot +- Check BIOS boot order +- Disable Secure Boot +### Disk not visible in WinPE +- Missing storage drivers +### Windows doesn't boot +- Re-run `bcdboot` +- Verify partition layout + +--- + +## Reference Documentation +- [WinPE overview](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/winpe-intro) +- [Create a USB drive with WinPE and data partitions](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/winpe--use-a-single-usb-key-for-winpe-and-a-wim-file---wim#create-a-usb-drive-with-winpe-and-data-partitions) +- [WinPE: Create bootable media](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/winpe-create-usb-bootable-drive) +- [Capture and apply Windows (WIM)](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/capture-and-apply-windows-using-a-single-wim) +- [Answer files (unattend.xml)](https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/update-windows-settings-and-scripts-create-your-own-answer-file-sxs)
\ No newline at end of file diff --git a/.github/crashdetect/Unattend.xml b/.github/crashdetect/Unattend.xml new file mode 100644 index 00000000..a235fba0 --- /dev/null +++ b/.github/crashdetect/Unattend.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<unattend xmlns="urn:schemas-microsoft-com:unattend" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-International-Core" + processorArchitecture="amd64" + publicKeyToken="31bf3856ad364e35" + language="neutral" + versionScope="nonSxS"> + <InputLocale>en-US</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UserLocale>en-US</UserLocale> + </component> + + <component name="Microsoft-Windows-Shell-Setup" + processorArchitecture="amd64" + publicKeyToken="31bf3856ad364e35" + language="neutral" + versionScope="nonSxS"> + + <TimeZone>Pacific Standard Time</TimeZone> + + <!-- Skip all OOBE --> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>3</ProtectYourPC> + </OOBE> + + <UserAccounts> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Name>admin</Name> + <Group>Administrators</Group> + <Password> + <Value>@Password123</Value> + <PlainText>true</PlainText> + </Password> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + + <!-- Auto logon (lab only) --> + <AutoLogon> + <Username>admin</Username> + <Enabled>true</Enabled> + <Password> + <Value>@Password123</Value> + <PlainText>true</PlainText> + </Password> + <LogonCount>999</LogonCount> + </AutoLogon> + + </component> + </settings> + +</unattend>
\ No newline at end of file diff --git a/.github/pdu/Pdu.ps1 b/.github/pdu/Pdu.ps1 new file mode 100644 index 00000000..b87fd470 --- /dev/null +++ b/.github/pdu/Pdu.ps1 @@ -0,0 +1,250 @@ +# ====================================================================== +# +# Manufacturer: Eaton Tripp Lite Switched Power Distribution Unit (PDU) +# Website: https://www.eaton.com/us/en-us/skuPage.PDUMH15NET.html +# Model: PDUMH15NET +# SNMP/Web Management Accessory Card: WEBCARDLX +# +# HW Requirements: Ethernet cable or USBA-to-MicroUSB cable. +# SW Requirements: Plink.exe from PuTTY terminal client SW (if Ethernet) +# PuTTY: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html +# +# Script: PowerShell script for turning ON/OFF and power CYCLING the PDU +# Usage: .\Pdu.ps1 [on | off | cycle] [1-16] +# +# ====================================================================== + +param( + [Parameter(Mandatory=$true, Position=0)] + [ValidateSet("cycle","on","off")] + [string]$Action, + + [Parameter(Mandatory=$true, Position=1)] + [ValidateRange(1,16)] + [int]$LoadNumber +) + +# ========================= +# Configuration +# ========================= +$ComNumber = 3 +$ComPort = "COM$ComNumber" + +$PduIP = "169.254.0.1" +$SshPort = 22 + +$Username = "localadmin" +$Password = "@Password123" + +$Plink = "C:\Program Files\PuTTY\plink.exe" + +# ========================= +# Helper Functions +# ========================= + +function Test-PduSerialConnection +{ + [bool]$Connected = $false + + try + { + $Port = New-Object System.IO.Ports.SerialPort $ComPort,115200,None,8,one + $Port.ReadTimeout = 3000 + $Port.WriteTimeout = 3000 + $Port.Open() + Start-Sleep 5 + $Port.DiscardOutBuffer() + $Port.DiscardInBuffer() + $null = $Port.ReadExisting() + + # Wake up console + $Port.WriteLine("") + Start-Sleep 2 + + $Banner = $Port.ReadExisting() + if ($Banner -match "login|localadmin|PowerAlert|Ubuntu") { + Write-Host "PDU detected on serial connection at $ComPort" + $Connected = $true + } else { + Write-Host "PDU NOT detected on serial connection at $ComPort" -ForegroundColor Yellow + } + } + catch + { + Write-Host "Unable to communicate on serial connection at $ComPort" -ForegroundColor Yellow + Write-Host $_.Exception.Message + } + finally + { + if ($Port -and $Port.IsOpen) { + $Port.DiscardOutBuffer() + $Port.DiscardInBuffer() + if ($Port.BytesToRead -gt 0) { + $null = $Port.ReadExisting() + } + $Port.Close() + } + + $Port.Dispose() + $Port = $null + } + return $Connected +} + +function Send-PduSerialCommand +{ + param([string]$Action) + + $Port = New-Object System.IO.Ports.SerialPort $ComPort,115200,None,8,one + + try + { + $Port.ReadTimeout = 3000 + $Port.WriteTimeout = 3000 + + $Port.Open() + Start-Sleep 5 + $Port.DiscardOutBuffer() + $Port.DiscardInBuffer() + $null = $Port.ReadExisting() + + Write-Host "Using SERIAL connection..." -ForegroundColor Green + $Port.WriteLine("") + Start-Sleep 2 + + Write-Host "Sending Username to PDU..." + $Port.WriteLine($Username) + Start-Sleep 2 + + Write-Host "Sending Password to PDU..." + $Port.WriteLine($Password) + Start-Sleep 5 + + # Sending [ cycle | on | off ] command to PDU. + Write-Host "Sending '$Action' command to PDU..." + $Port.WriteLine("device; load $LoadNumber; $Action force") + Start-Sleep 2 + + # "Sending Exit command to PDU..." + $Port.WriteLine("exit; exit; exit") + Start-Sleep 2 + } + catch + { + Write-Host "Unable to communicate with $ComPort" + Write-Host $_.Exception.Message + } + finally + { + if ($Port -and $Port.IsOpen) { + $Port.DiscardOutBuffer() + $Port.DiscardInBuffer() + if ($Port.BytesToRead -gt 0) { + $null = $Port.ReadExisting() + } + $Port.Close() + Write-Host "Closed serial port $ComPort" + } + if ($Port) + { + $Port.Dispose() + } + $Port = $null + } +} + +function Test-PduNetworkConnection +{ + [bool]$Connected = $false + + try + { + $Client = New-Object System.Net.Sockets.TcpClient +# $Client.Connect($PduIP,$SshPort) + + $Result = $Client.BeginConnect($PduIP,$SshPort,$null,$null) + if (-not $Result.AsyncWaitHandle.WaitOne(3000)) + { + throw "Connection timeout" + } + $Client.EndConnect($Result) + + $Stream = $Client.GetStream() + Start-Sleep 1 + + $Buffer = New-Object byte[] 1024 + $Stream.ReadTimeout = 3000 + $Bytes = $Stream.Read($Buffer,0,$Buffer.Length) + + $Banner = [System.Text.Encoding]::ASCII.GetString($Buffer,0,$Bytes) + + if ($Banner -match "login|localadmin|PowerAlert|Ubuntu") { + Write-Host "PDU detected on network connection at IP: $PduIP, Port: $SshPort" + $Connected = $true + } + else { + Write-Host "PDU NOT detected on network connection at IP: $PduIP, Port: $SshPort" -ForegroundColor Yellow + } + + $Client.Close() + } + catch + { + Write-Host "Unable to establish network connection at IP: $PduIP, Port: $SshPort" -ForegroundColor Yellow + Write-Host $_.Exception.Message + } + return $Connected +} + +function Send-PduNetworkCommand +{ + param([string]$Action) + + if (-not (Test-Path $Plink)) + { + throw "plink.exe not found: $Plink" + } + + Write-Host "Using NETWORK connection..." -ForegroundColor Green + + $Command = "device; load $LoadNumber; $Action force; exit; exit; exit" + + $Command | & $Plink ` + -ssh ` + -batch ` + -pw $Password ` + "$Username@$PduIP" ` +} + +# ========================= +# Main Logic +# ========================= + +Write-Host "" +Write-Host "Requested Action : $Action" +Write-Host "" + +# First choice = Serial +if (Test-PduSerialConnection) +{ + Send-PduSerialCommand $Action + exit 0 +} + +Write-Host "Serial connection not available." +Write-Host "Trying network connection..." + +# Second choice = Network +if (Test-PduNetworkConnection) +{ + Send-PduNetworkCommand $Action + exit 0 +} + +Write-Host "" +Write-Host "ERROR: No PDU connection available." -ForegroundColor Red +Write-Host " Serial : $ComPort" +Write-Host " Ethernet : $PduIP" +Write-Host "" + +exit 1
\ No newline at end of file diff --git a/.github/pdu/PduReadme.md b/.github/pdu/PduReadme.md new file mode 100644 index 00000000..524bddd2 --- /dev/null +++ b/.github/pdu/PduReadme.md @@ -0,0 +1,65 @@ +# PDU Setup: <br>Eaton Tripp Lite Switched Power Distribution Unit (PDUMH15NET) + +## Requirements: +### HW: + - USBA-to-MicroUSB cable, needed for 1st time PDU login and password change, if IP address is unknown. + - Ethernet cable, can be used if the IP address is known. +### SW: + - [Tera Term 5.6.1 terminal client:](https://github.com/TeraTermProject/teraterm/releases/tag/v5.6.1) + - Terminal client for PDU login and configuration via serial. + - [PuTTY 0.84 terminal client:](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) + - `Plink.exe` needed for PowerShell scripting via network. + - **Note**: PuTTY terminal client GUI does not appear to work, so Tera Term client was used instead, but `Plink.exe` is needed for passing passwords via SSH in PowerShell scripts. + +## Serial Connection +### What's my IP address? +- If the PDU is connected to a network with **DHCP**, then we need to find it's IP address first by using serial connection. + - If the PDU is not connected to a network with DHCP, then its default static IP address should be `169.254.0.1`. + - If that's the case, then you can login to the PDU via a browser by skipping the the section Network Connection. + +Tera Term: +- Connect the PC to the PDU (CONFIG port) with a USBA-to-MiniUSB cable. +- On the PC, go to Device Manager and verify under `Ports (COM & LPT)`, the `USB Serial Device (COM3)` device is present. +- Download and install Tera Term on PC, if not already present. + - You may use other Terminal Emulation Programs, but this is the one used in the manufacturer's user manual to connect to the WEBCARDLX network interface card. +- Launch Tera Term and select the "Serial" connection type and ensure `Port: "COM3: USB Serial Device (COM3)` is selected, then click "OK". +- When the blinking cursor in the empty prompt stops blinking, hit Enter key to wake up console. +- The `Ubuntu 18.04.6 LTS poweralert-0006674a215f` (<-- MAC Address) should show up in the prompt asking for login. + - Default login is: `localadmin` + - Default 1st time password is: `localadmin` + - Must change password after 1st logon. + - Change password to `@Password123` to match what the `pdu.ps1` PowerShell script uses. +- Once logged in, type `show network` to display network information such as current IP address. + - If on DHCP network, note the IP address assigned to the PDU. + - PDU default if no DHCP: + - IPv4: `169.254.0.1` + - Subnet Mask: `255.255.0.0` +- Test pinging the IPv4 address of the PDU from the PC. + - `ping <IP Address>` +- Now that you have the IP address, it may be easier to switch over to the browser interface to configure the rest of the PDU. + +## Network Connection +- Connect an Ethernet cable from the PC to the PDU Ethernet port. +- Since we have the IP of the PDU, it's easier to configure the PDU via a browser interface. +- Open an Internet browser and enter the IPv4 address of the PDU into the browser. + - If it prompts you about any security warnings, just find a way to accept and continue anyway. +- The `Power Alert LX` web interface should prompt for username and password. +- If 1st time login... + - Default login is: `localadmin` + - Default 1st time password is: `localadmin` + - Must change password after 1st logon. + - Change password to `@Password123` to match what the `pdu.ps1` PowerShell script uses. +- Select `Load` tab on the left of screen to see all the loads on the 16 power ports. +- Click on the `State` slider to show the Load options, `Turn Off Load` and `Cycle Load`. +- To enable SSH for PowerShell scripting later, select `Network` tab, then `Services`, then enable `SSH Enabled`. + +## Scripting +- The `Pdu.ps1` PowerShell script can be used for automating power ON/OFF/CYCLE of the PDU ports. +- Usage: `.\Pdu.ps1 [on | off | cycle] [1-16]` +- Update the following variables in the `Pdu.ps1` script if necessary. + - `$PduIP = "169.254.0.1"` + - `$Password = "@Password123"` +- The script will check first if there's a serial connection first, then network connection if serial is not present, before issuing the PDU command. + +## References +- Eaton Tripp Lite Switched PDU (PDUMH15NET): [Manuals & User Guides](https://www.eaton.com/us/en-us/skuPage.PDUMH15NET.html#tab-2)
\ No newline at end of file diff --git a/.github/scripts/Build-ChangedSamples.ps1 b/.github/scripts/Build-ChangedSamples.ps1 index bdaee943..f03f93f3 100644 --- a/.github/scripts/Build-ChangedSamples.ps1 +++ b/.github/scripts/Build-ChangedSamples.ps1 @@ -22,7 +22,7 @@ foreach ($file in $ChangedFiles) { $filename = Split-Path $file -Leaf # Files that can affect how every sample is built should trigger a full build - if ($filename -eq "Build-AllSamples.ps1" -or $filename -eq "Build-Sample.ps1" -or $filename -eq "Build-SampleSet.ps1" -or $filename -eq "exclusions.csv" -or $filename -eq "Directory.Build.props" -or $filename -eq "packages.config") { + if ($filename -eq "Build-Samples.ps1" -or $filename -eq "Get-NtTargetVersions.ps1" -or $filename -eq "exclusions.csv" -or $filename -eq "Directory.Build.props" -or $filename -eq "packages.config") { $buildAll = $true } if ($dir -like "$root\.github\scripts" -or $dir -like "$root\.github\scripts\*") { @@ -52,9 +52,10 @@ foreach ($file in $ChangedFiles) { } if ($buildAll) { - .\Build-AllSamples -Verbose:$Verbose -LogFilesDirectory (Join-Path $root "_logs") + .\Build-Samples -Verbose:$Verbose -LogFilesDirectory (Join-Path $root "_logs") } else { - .\Build-SampleSet -SampleSet $sampleSet -Verbose:$Verbose -LogFilesDirectory (Join-Path $root "_logs") + $sampleNames = $sampleSet.Keys | Sort-Object + .\Build-Samples -Samples $sampleNames -Verbose:$Verbose -LogFilesDirectory (Join-Path $root "_logs") } diff --git a/.github/scripts/Join-CsvReports.ps1 b/.github/scripts/Join-CsvReports.ps1 index 32cd9d63..43e0c826 100644 --- a/.github/scripts/Join-CsvReports.ps1 +++ b/.github/scripts/Join-CsvReports.ps1 @@ -1,35 +1,201 @@ -$logsPath = Join-Path (Get-Location).Path "_logs" +<# +.SYNOPSIS + Joins the per-job Build-Samples CSV reports (one per _NT_TARGET_VERSION x configuration x + platform) into a single overview, and writes an easy-to-scan summary to the GitHub Actions + run page ($GITHUB_STEP_SUMMARY). + +.DESCRIPTION + Each build job uploads a "_logs" folder containing a report named + _overview.<ntTag>.<configuration>.<platform>.csv + with columns: Sample, <Configuration|Platform> (one combination per file). This script: + * parses the _NT_TARGET_VERSION tag and combination from every report, + * collapses each sample's combinations into one status per version, + * writes _overview.all.csv / _overview.all.htm (a colour-coded sample x version matrix), and + * appends a Markdown summary (per-version totals + a failures table) to $GITHUB_STEP_SUMMARY + so failures are obvious from the run page without opening any logs. + + The older 2-part name (_overview.<configuration>.<platform>.csv, no version) is still + understood and bucketed under the "latest" column. +#> + +$logsPath = Join-Path (Get-Location).Path "_logs" $reportFileName = '_overview.all' -$idProperty = 'Sample' -$results = $null -Get-ChildItem -Path $logsPath -Filter '*.csv' | ForEach-Object { - $csv = Import-Csv -Path $_ - if ($results -eq $null) { - $results = $csv +if (-not (Test-Path $logsPath)) { + Write-Warning "No _logs directory found at $logsPath - nothing to report." + return +} + +# --- Load every per-job CSV --------------------------------------------------- +# data[sample][tag][combo] = status +$data = @{} +$allSamples = [System.Collections.Generic.SortedSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) +$tagSet = [System.Collections.Generic.HashSet[string]]::new() + +Get-ChildItem -Path $logsPath -Filter '_overview.*.csv' | + Where-Object { $_.Name -notlike '_overview.all.*' } | + ForEach-Object { + # _overview.<tag>.<config>.<platform> -> drop _overview; last two are config/platform. + $parts = [IO.Path]::GetFileNameWithoutExtension($_.Name).Split('.') + $parts = $parts[1..($parts.Count - 1)] # drop the leading "_overview" + if ($parts.Count -ge 3) { $tag = ($parts[0..($parts.Count - 3)] -join '.') } + else { $tag = 'latest' } + [void]$tagSet.Add($tag) + + Import-Csv -Path $_.FullName | ForEach-Object { + $sample = $_.Sample + if (-not $sample) { return } + [void]$allSamples.Add($sample) + if (-not $data.ContainsKey($sample)) { $data[$sample] = @{} } + if (-not $data[$sample].ContainsKey($tag)) { $data[$sample][$tag] = @{} } + foreach ($col in ($_.PSObject.Properties.Name | Where-Object { $_ -ne 'Sample' })) { + $data[$sample][$tag][$col] = "$($_.$col)".Trim() + } + } } - else { - $results = $csv | ForEach-Object { - $id = $_.$idProperty - $match = $results | Where-Object { $_.$idProperty -eq $id } - if ($match) { - $properties = $_ | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -ne $idProperty } | Select-Object -ExpandProperty Name - $newObject = New-Object PSObject - # Add ID property separately to ensure it appears first - $newObject | Add-Member -MemberType NoteProperty -Name $idProperty -Value $_.$idProperty - foreach ($property in $properties) { - $newObject | Add-Member -MemberType NoteProperty -Name $property -Value $_.$property - } - foreach ($property in ($match | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -ne $idProperty } | Select-Object -ExpandProperty Name)) { - if ($properties -notcontains $property) { - $newObject | Add-Member -MemberType NoteProperty -Name $property -Value $match.$property - } - } - $newObject + +if ($tagSet.Count -eq 0) { + Write-Warning "No per-job '_overview.*.csv' reports were found in $logsPath." + return +} + +# Order versions newest-first (numeric tags descending; non-numeric last) +$tags = $tagSet | Sort-Object @{ Expression = { if ($_ -match '^\d+$') { [int]$_ } else { 0 } }; Descending = $true }, @{ Expression = { $_ } } + +function Get-Status { + # Collapse one sample/version's combinations into a single status object. + param([hashtable]$Combos) + $c = @{ Succeeded = 0; Failed = 0; Sporadic = 0; Unsupported = 0; Excluded = 0 } + $details = @() + if ($Combos) { + foreach ($k in ($Combos.Keys | Sort-Object)) { + switch ($Combos[$k]) { + 'Succeeded' { $c.Succeeded++ } 'Failed' { $c.Failed++ } 'Sporadic' { $c.Sporadic++ } + 'Unsupported' { $c.Unsupported++ } 'Excluded' { $c.Excluded++ } + } + $details += "$k = $($Combos[$k])" + } + } + $buildable = $c.Succeeded + $c.Failed + $c.Sporadic + if (-not $Combos -or $Combos.Count -eq 0) { $label = 'n/a'; $klass = 'na' } + elseif ($buildable -eq 0) { $label = '--'; $klass = 'na' } + elseif ($c.Failed -eq 0 -and $c.Sporadic -eq 0) { $label = "PASS ($($c.Succeeded)/$buildable)"; $klass = 'pass' } + elseif ($c.Failed -eq 0) { $label = "PASS* ($($c.Succeeded + $c.Sporadic)/$buildable)"; $klass = 'flaky' } + elseif ($c.Failed -eq $buildable) { $label = "FAIL ($($c.Failed)/$buildable)"; $klass = 'fail' } + else { $label = "PARTIAL ($($c.Failed) failed / $buildable)"; $klass = 'partial' } + [pscustomobject]@{ Label = $label; Class = $klass; Tooltip = ($details -join ' | '); Counts = $c; Buildable = $buildable } +} + +# --- Build per-version totals + the matrix ------------------------------------ +$totals = @{}; foreach ($t in $tags) { $totals[$t] = [pscustomobject]@{ S = 0; F = 0; O = 0; U = 0; E = 0; pass = 0; flaky = 0; partial = 0; fail = 0; na = 0 } } +$failuresList = [System.Collections.ArrayList]::new() +$csvRows = @() +$bodyRows = New-Object System.Text.StringBuilder + +foreach ($sample in $allSamples) { + $csvRow = [ordered]@{ Sample = $sample } + $cells = '' + foreach ($t in $tags) { + $combos = $null + if ($data[$sample].ContainsKey($t)) { $combos = $data[$sample][$t] } + $st = Get-Status -Combos $combos + $tt = $totals[$t] + $tt.S += $st.Counts.Succeeded; $tt.F += $st.Counts.Failed; $tt.O += $st.Counts.Sporadic + $tt.U += $st.Counts.Unsupported; $tt.E += $st.Counts.Excluded + switch ($st.Class) { 'pass' { $tt.pass++ } 'flaky' { $tt.flaky++ } 'partial' { $tt.partial++ } 'fail' { $tt.fail++ } 'na' { $tt.na++ } } + $csvRow["$t"] = $st.Label + $tip = [System.Web.HttpUtility]::HtmlEncode($st.Tooltip) + $cells += "<td class='$($st.Class)' title='$tip'>$($st.Label)</td>" + if ($combos) { + foreach ($k in ($combos.Keys | Sort-Object)) { + if ($combos[$k] -eq 'Failed') { [void]$failuresList.Add([pscustomobject]@{ Sample = $sample; Version = $t; Combo = $k }) } } } } + $csvRows += [pscustomobject]$csvRow + $enc = [System.Web.HttpUtility]::HtmlEncode($sample) + [void]$bodyRows.Append("<tr><td class='sample'>$enc</td>$cells</tr>`n") } -$results | ConvertTo-Csv | Out-File (Join-Path $logsPath "$reportFileName.csv") -$results | ConvertTo-Html -Title "Overview" | Out-File (Join-Path $logsPath "$reportFileName.htm") +Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue + +# --- CSV ---------------------------------------------------------------------- +$csvRows | Export-Csv -Path (Join-Path $logsPath "$reportFileName.csv") -NoTypeInformation + +# --- HTML (colour-coded sample x version matrix) ------------------------------ +$generated = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' +$sumHead = "<tr><th>_NT_TARGET_VERSION</th><th>Pass</th><th>Flaky</th><th>Partial</th><th>Fail</th><th>n/a</th><th>Combos OK</th><th>Sporadic</th><th>Failed</th><th>Excluded</th><th>Pass rate</th></tr>" +$sumRows = '' +foreach ($t in $tags) { + $x = $totals[$t]; $tot = $x.pass + $x.flaky + $x.partial + $x.fail + $x.na; $elig = $tot - $x.na + $rate = if ($elig -gt 0) { '{0:N0}%' -f (100.0 * ($x.pass + $x.flaky) / $elig) } else { 'n/a' } + $sumRows += "<tr><td class='sample'>$t</td><td class='pass'>$($x.pass)</td><td class='flaky'>$($x.flaky)</td><td class='partial'>$($x.partial)</td><td class='fail'>$($x.fail)</td><td class='na'>$($x.na)</td><td>$($x.S)</td><td>$($x.O)</td><td>$($x.F)</td><td>$($x.E)</td><td><b>$rate</b></td></tr>`n" +} +$matHead = "<tr><th class='sample'>Sample</th>" +foreach ($t in $tags) { $matHead += "<th>$t</th>" } +$matHead += "</tr>" + +$html = @" +<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/> +<title>WDK Driver Samples - Build Overview</title> +<style> + body{font-family:'Segoe UI',Arial,sans-serif;margin:24px;color:#1b1b1b} + h1{font-size:22px;margin-bottom:4px}h2{font-size:17px;margin-top:28px} + .meta{color:#555;font-size:13px;margin-bottom:8px} + table{border-collapse:collapse;margin-top:8px;font-size:13px} + th,td{border:1px solid #cfcfcf;padding:5px 9px;text-align:center} + th{background:#f0f3f7;position:sticky;top:0} + td.sample,th.sample{text-align:left;font-family:Consolas,monospace;white-space:nowrap} + .sub{font-weight:normal;color:#666;font-size:11px} + .pass{background:#c8e6c9}.flaky{background:#fff59d}.partial{background:#ffcc80}.fail{background:#ef9a9a}.na{background:#eee;color:#888} + .legend span{display:inline-block;padding:3px 9px;margin-right:6px;border:1px solid #cfcfcf;border-radius:3px;font-size:12px} +</style></head><body> +<h1>WDK Driver Samples — Build Overview</h1> +<div class="meta">Generated: $generated | columns are <b>_NT_TARGET_VERSION</b> (library link version); hover a cell for the per-combination breakdown.</div> +<div class="legend"><span class="pass">PASS</span><span class="flaky">PASS* (retry)</span><span class="partial">PARTIAL</span><span class="fail">FAIL</span><span class="na">-- n/a</span></div> +<h2>Summary by _NT_TARGET_VERSION</h2> +<table>$sumHead +$sumRows</table> +<h2>Sample × _NT_TARGET_VERSION</h2> +<table>$matHead +$($bodyRows.ToString())</table> +</body></html> +"@ +$html | Out-File -FilePath (Join-Path $logsPath "$reportFileName.htm") -Encoding UTF8 + +# --- GitHub Actions run summary (Markdown) ------------------------------------ +if ($env:GITHUB_STEP_SUMMARY) { + $totalFailed = ($totals.Values | Measure-Object -Property fail -Sum).Sum + ($totals.Values | Measure-Object -Property partial -Sum).Sum + $icon = if ($failuresList.Count -gt 0) { ':x:' } else { ':white_check_mark:' } + + $md = [System.Text.StringBuilder]::new() + [void]$md.AppendLine("# $icon WDK Driver Samples — Build Overview") + [void]$md.AppendLine() + [void]$md.AppendLine("Columns are **_NT_TARGET_VERSION** (the WDK library version drivers link against). Each version was built for Debug/Release x x64/arm64.") + [void]$md.AppendLine() + [void]$md.AppendLine("## Summary by _NT_TARGET_VERSION") + [void]$md.AppendLine("| _NT_TARGET_VERSION | :white_check_mark: Pass | :warning: Flaky | :large_orange_diamond: Partial | :x: Fail | :heavy_minus_sign: n/a | Pass rate |") + [void]$md.AppendLine("|---|---:|---:|---:|---:|---:|---:|") + foreach ($t in $tags) { + $x = $totals[$t]; $tot = $x.pass + $x.flaky + $x.partial + $x.fail + $x.na; $elig = $tot - $x.na + $rate = if ($elig -gt 0) { '{0:N0}%' -f (100.0 * ($x.pass + $x.flaky) / $elig) } else { 'n/a' } + [void]$md.AppendLine("| ``$t`` | $($x.pass) | $($x.flaky) | $($x.partial) | $($x.fail) | $($x.na) | **$rate** |") + } + [void]$md.AppendLine() + + if ($failuresList.Count -gt 0) { + [void]$md.AppendLine("## :x: Failures ($($failuresList.Count))") + [void]$md.AppendLine("| Sample | _NT_TARGET_VERSION | Config/Platform |") + [void]$md.AppendLine("|---|---|---|") + foreach ($f in ($failuresList | Sort-Object Sample, Version, Combo)) { + [void]$md.AppendLine("| ``$($f.Sample)`` | $($f.Version) | $($f.Combo.Replace('|','/')) |") + } + [void]$md.AppendLine() + [void]$md.AppendLine("> Open the matching **build** job's summary (or the ``logs-*`` artifact) for the exact compiler error.") + } + else { + [void]$md.AppendLine(":tada: **All combinations built successfully.**") + } + + $md.ToString() | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8 +} diff --git a/.github/workflows/Code-Scanning.yml b/.github/workflows/Code-Scanning.yml index 63e155c9..06346d21 100644 --- a/.github/workflows/Code-Scanning.yml +++ b/.github/workflows/Code-Scanning.yml @@ -26,7 +26,7 @@ on: jobs: analyze: name: Analysis - runs-on: windows-latest + runs-on: windows-2025-vs2026 permissions: actions: read contents: read @@ -48,7 +48,7 @@ jobs: run: nuget restore .\packages.config -PackagesDirectory .\packages\ - name: Get changed files id: get-changed-files - uses: tj-actions/changed-files@v41 + uses: tj-actions/changed-files@v46 with: separator: "," - name: Initialize CodeQL @@ -66,7 +66,7 @@ jobs: WDS_Platform: x64 WDS_WipeOutputs: ${{ true }} - if: github.event_name == 'push' - run: .\Build-AllSamples.ps1 -Verbose -ThrottleLimit 1 + run: .\Build-Samples.ps1 -Verbose -ThrottleLimit 1 env: WDS_Configuration: Debug WDS_Platform: x64 diff --git a/.github/workflows/check-sample-issue-template.yml b/.github/workflows/check-sample-issue-template.yml new file mode 100644 index 00000000..7e17bedd --- /dev/null +++ b/.github/workflows/check-sample-issue-template.yml @@ -0,0 +1,50 @@ +name: Check Sample Issue Template + +on: + pull_request: + paths: + - '.github/CODEOWNERS' + - '.github/ISSUE_TEMPLATE/sample_issue.yml' + - '.github/ISSUE_TEMPLATE/sample_issue_generator.py' + + +jobs: + generate-template: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + run: pip install pyyaml + + - name: Run the generator script + run: python .github/ISSUE_TEMPLATE/sample_issue_generator.py + + - name: Check for discrepancies + run: | + if git diff --quiet .github/ISSUE_TEMPLATE/sample_issue.yml; then + echo "✅ No discrepancies found. The sample issue template is up to date." + else + echo "❌ Discrepancy detected!" + echo "The CODEOWNERS file was modified, but the sample issue template is not up to date." + echo "" + echo "Please regenerate the sample issue template by running:" + echo " python .github/ISSUE_TEMPLATE/sample_issue_generator.py" + echo "" + echo "Or manually update it." + echo "" + echo "Then commit both files together:" + echo " git add .github/CODEOWNERS .github/ISSUE_TEMPLATE/sample_issue.yml" + echo " git commit -m 'Update CODEOWNERS and regenerate sample issue template'" + echo "" + echo "Differences found:" + git diff .github/ISSUE_TEMPLATE/sample_issue.yml + exit 1 + fi diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index 0e5825d1..8119c94c 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -8,14 +8,40 @@ on: - '**.md' - 'LICENSE' jobs: + # Auto-discover the available _NT_TARGET_VERSION values from the active WDK so the build + # matrix never needs a hand-maintained version list. Change -Newest to build more/fewer. + discover: + name: discover _NT_TARGET_VERSIONs + runs-on: windows-2025-vs2026 + outputs: + versions: ${{ steps.nt.outputs.versions }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Install Nuget Packages + run: nuget restore .\packages.config -PackagesDirectory .\packages\ + + - name: Discover the newest _NT_TARGET_VERSION values + id: nt + shell: pwsh + run: | + $json = .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson + "versions=$json" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + Write-Host "Discovered _NT_TARGET_VERSION matrix: $json" + build: - name: Build driver samples + name: build ${{ matrix.nt.tag }} ${{ matrix.configuration }} ${{ matrix.platform }} + needs: discover strategy: fail-fast: false matrix: configuration: [Debug, Release] platform: [x64, arm64] - runs-on: windows-2022 + # _NT_TARGET_VERSION values are auto-discovered by the 'discover' job from the active + # WDK, so there is no version list to maintain here. + nt: ${{ fromJSON(needs.discover.outputs.versions) }} + runs-on: windows-2025-vs2026 steps: - name: Check out repository code uses: actions/checkout@v4 @@ -38,13 +64,14 @@ jobs: env: WDS_Configuration: ${{ matrix.configuration }} WDS_Platform: ${{ matrix.platform }} - WDS_ReportFileName: _overview.${{ matrix.configuration }}.${{ matrix.platform }} + WDS_NtTargetVersion: ${{ matrix.nt.version }} + WDS_ReportFileName: _overview.${{ matrix.nt.tag }}.${{ matrix.configuration }}.${{ matrix.platform }} - name: Archive build logs and overview build reports uses: actions/upload-artifact@v4 if: always() with: - name: logs-${{ matrix.configuration }}-${{ matrix.platform }} + name: logs-${{ matrix.nt.tag }}-${{ matrix.configuration }}-${{ matrix.platform }} path: _logs report: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f3d7693..4b263a82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,7 @@ name: Build all driver samples on: + # Allows the workflow to be triggered manually from the Actions tab ("Run workflow"). + workflow_dispatch: push: branches: - main @@ -11,14 +13,40 @@ on: # Runs every Saturday at 00:00 PST (08:00 UTC) - cron: '0 8 * * 6' jobs: + # Auto-discover the available _NT_TARGET_VERSION values from the active WDK so the build + # matrix never needs a hand-maintained version list. Change -Newest to build more/fewer. + discover: + name: discover _NT_TARGET_VERSIONs + runs-on: windows-2025-vs2026 + outputs: + versions: ${{ steps.nt.outputs.versions }} + steps: + - name: Check out repository code + uses: actions/checkout@v4 + + - name: Install Nuget Packages + run: nuget restore .\packages.config -PackagesDirectory .\packages\ + + - name: Discover the newest _NT_TARGET_VERSION values + id: nt + shell: pwsh + run: | + $json = .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson + "versions=$json" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + Write-Host "Discovered _NT_TARGET_VERSION matrix: $json" + build: - name: Build driver samples + name: build ${{ matrix.nt.tag }} ${{ matrix.configuration }} ${{ matrix.platform }} + needs: discover strategy: fail-fast: false matrix: configuration: [Debug, Release] platform: [x64, arm64] - runs-on: windows-2022 + # _NT_TARGET_VERSION values are auto-discovered by the 'discover' job from the active + # WDK, so there is no version list to maintain here. + nt: ${{ fromJSON(needs.discover.outputs.versions) }} + runs-on: windows-2025-vs2026 steps: - name: Check out repository code uses: actions/checkout@v4 @@ -29,17 +57,18 @@ jobs: run: nuget restore .\packages.config -PackagesDirectory .\packages\ - name: Retrieve and build all available solutions - run: .\Build-AllSamples.ps1 -Verbose + run: .\Build-Samples.ps1 -Verbose env: WDS_Configuration: ${{ matrix.configuration }} WDS_Platform: ${{ matrix.platform }} - WDS_ReportFileName: _overview.${{ matrix.configuration }}.${{ matrix.platform }} + WDS_NtTargetVersion: ${{ matrix.nt.version }} + WDS_ReportFileName: _overview.${{ matrix.nt.tag }}.${{ matrix.configuration }}.${{ matrix.platform }} - name: Archive build logs and overview build reports uses: actions/upload-artifact@v4 if: always() with: - name: logs-${{ matrix.configuration }}-${{ matrix.platform }} + name: logs-${{ matrix.nt.tag }}-${{ matrix.configuration }}-${{ matrix.platform }} path: _logs report: diff --git a/.github/workflows/tag-codeowner-on-issue.yml b/.github/workflows/tag-codeowner-on-issue.yml new file mode 100644 index 00000000..a4fe365d --- /dev/null +++ b/.github/workflows/tag-codeowner-on-issue.yml @@ -0,0 +1,82 @@ +name: Tag Codeowner on Sample Issue + +on: + issues: + types: [opened] + +jobs: + tag-codeowner: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + run: pip install pyyaml requests + + - name: Extract selected path and tag codeowner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_BODY: ${{ github.event.issue.body }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + run: | + python3 - <<EOF + import os + import re + import requests + + issue_body = os.environ['ISSUE_BODY'] + selected_path = None + + # Try to extract the selected path from the issue body + match = re.search(r'### Which is the area where the sample lives\?\s*\n(.+)', issue_body, re.MULTILINE) + if match: + selected_path = match.group(1).strip() + + if not selected_path: + print("No sample path found in issue body.") + exit(0) + + # Read CODEOWNERS + with open(".github/CODEOWNERS", "r") as f: + lines = f.readlines() + + codeowner = None + sample_section = False + for line in lines: + line = line.strip() + if line.startswith("# Samples"): + sample_section = True + continue + if sample_section: + if line.startswith("#") or not line: + continue + path, owner = line.split() + if path == selected_path: + codeowner = owner + break + + if codeowner is None: + print(f"No codeowner found for path: {selected_path}") + exit(0) + + # Post a comment tagging the owner + comment = f"{codeowner} can you please take a look at this issue related to {selected_path}?" + repo = os.environ['GITHUB_REPOSITORY'] + token = os.environ['GITHUB_TOKEN'] + issue_number = os.environ['ISSUE_NUMBER'] + + url = f"https://api.github.com/repos/{repo}/issues/{issue_number}/comments" + headers = { + "Authorization": f"Bearer {token}", + "Accept": "application/vnd.github.v3+json" + } + response = requests.post(url, headers=headers, json={"body": comment}) + print("Comment posted:", response.status_code, response.text) + EOF diff --git a/Build-AllSamples.ps1 b/Build-AllSamples.ps1 deleted file mode 100644 index 6b3a1976..00000000 --- a/Build-AllSamples.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -<# -.SYNOPSIS -Builds all available sample solutions in the repository (excluding specific solutions). - -.DESCRIPTION -This script searches for all available Visual Studio Solutions (.sln files) and attempts to run MSBuild to build them for the specified configurations and platforms. - -.PARAMETER Samples -A regular expression matching the samples to be built. Default is '' that matches all samples. Examples include '^tools.' or '.dchu'. - -.PARAMETER Configurations -A list of configurations to build samples under. Values available are 'Debug' and 'Release'. By default, $env:WDS_Configuration will be used as the sole configuration to build for. If this environment variable is not set the default is 'Debug' and 'Release'. - -.PARAMETER Platforms -A list of platforms to build samples under (e.g. 'x64', 'arm64'). By default, $env:WDS_Platform will be used as the sole platform to build for. If this environment variable is not set the default is 'x64' and'arm64'. - -.PARAMETER LogFilesDirectory -Path to a directory where the log files will be written to. If not provided, outputs will be logged to the '_logs' directory within the current working directory. - -.PARAMETER ThrottleLimit -An integer indicating how many combinations to build in parallel. If 0 or not provided this defaults to 5 x number of logical processors. - -.INPUTS -None. - -.OUTPUTS -None. - -.EXAMPLE -.\Build-AllSamples - -.EXAMPLE -.\Build-AllSamples -Samples '^tools.' -Configurations 'Debug','Release' -Platforms 'x64','arm64' - -#> - -[CmdletBinding()] -param( - [string]$Samples = "", - [string[]]$Configurations = @(if ([string]::IsNullOrEmpty($env:WDS_Configuration)) { ('Debug', 'Release') } else { $env:WDS_Configuration }), - [string[]]$Platforms = @(if ([string]::IsNullOrEmpty($env:WDS_Platform)) { ('x64', 'arm64') } else { $env:WDS_Platform }), - [string]$LogFilesDirectory = (Join-Path (Get-Location) "_logs"), - [int]$ThrottleLimit -) - -$Verbose = $false -if ($PSBoundParameters.ContainsKey('Verbose')) { - $Verbose = $PsBoundParameters.Get_Item('Verbose') -} - -$root = Get-Location -$solutionFiles = Get-ChildItem -Path $root -Recurse -Filter *.sln | Select-Object -ExpandProperty FullName - -# To include in CI gate -$sampleSet = @{} -foreach ($file in $solutionFiles) { - $dir = (Get-Item $file).DirectoryName - $dir_norm = $dir.Replace($root, '').Trim('\').Replace('\', '.').ToLower() - if ($dir_norm -match ("^packages.")) { - Write-Verbose "`u{1F50E} Found and ignored non-sample [$dir_norm] at $dir" - } - elseif ($dir_norm -match ($Samples)) { - Write-Verbose "`u{1F50E} Found and filtered in sample [$dir_norm] at $dir" - $sampleSet[$dir_norm] = $dir - } - else { - Write-Verbose "`u{1F50E} Found and filtered out sample [$dir_norm] at $dir" - } -} - -.\Build-SampleSet -SampleSet $sampleSet -Configurations $Configurations -Platform $Platforms -LogFilesDirectory $LogFilesDirectory -Verbose:$Verbose -ThrottleLimit $ThrottleLimit diff --git a/Build-Sample.ps1 b/Build-Sample.ps1 deleted file mode 100644 index 093ba1ed..00000000 --- a/Build-Sample.ps1 +++ /dev/null @@ -1,211 +0,0 @@ -<# -.SYNOPSIS -Builds an specific directory containing a sample solution. - -.DESCRIPTION -This script attempts to build a directory containing a driver sample Solution for the specified configurations and platforms. - -.PARAMETER Directory -Path to a directory containing a valid Visual Studio Solution (.sln file). This is the solution that will be built. - -.PARAMETER SampleName -A friendly name to refer to the sample. Is unspecified, a name will be automatically generated one from the sample path. - -.PARAMETER Configuration -Configuration name that will be used to build the solution. Common available values are "Debug" and "Release". - -.PARAMETER Platform -Platform to build the solution for (e.g. "x64", "arm64"). - -.PARAMETER InfVerif_AdditionalOptions -Additional options for infverif (e.g. "/samples"). - -.PARAMETER LogFilesDirectoy -Path to a directory where the log files will be written to. If not provided, outputs will be logged to the current working directory. - -.INPUTS -None. - -.OUTPUTS -Verbose output about the execution of this script will be provided only if -Verbose is provided. Otherwise, no output will be generated. - -.EXAMPLE -.\Build-Sample -Directory .\usb\kmdf_fx2 - -.EXAMPLE -.\Build-Sample -Directory .\usb\kmdf_fx2 -Configuration 'Release' -Platform 'x64' -Verbose -LogFilesDirectory .\_logs - -#> - -[CmdletBinding()] -param( - [Parameter(Mandatory = $true, - HelpMessage = 'Enter one directory path', - Position = 0)] - [string]$Directory, - [string]$SampleName, - [string]$Configuration = "Debug", - [string]$Platform = "x64", - [string]$InfVerif_AdditionalOptions = "/samples", - $LogFilesDirectory = (Get-Location) -) - -$Verbose = $false -if ($PSBoundParameters.ContainsKey('Verbose')) { - $Verbose = $PsBoundParameters.Get_Item('Verbose') -} - -$oldPreference = $ErrorActionPreference -$ErrorActionPreference = "stop" -try -{ - # Check that msbuild can be called before trying anything. - Get-Command "msbuild" | Out-Null -} -catch -{ - Write-Verbose "`u{274C} msbuild cannot be called from current environment. Check that msbuild is set in current path (for example, that it is called from a Visual Studio developer command)." - Write-Error "msbuild cannot be called from current environment." - exit 1 -} -finally -{ - $ErrorActionPreference = $oldPreference -} - -if (-not (Test-Path -Path $Directory -PathType Container)) -{ - Write-Warning "`u{274C} A valid directory could not be found under $Directory" - exit 1 -} - -New-Item -ItemType Directory -Force -Path $LogFilesDirectory | Out-Null - -if (-not (Test-Path -Path $LogFilesDirectory -PathType Container)) -{ - Write-Warning "`u{274C} A valid directory for storing log files could not be created under $LogFilesDirectory" - # No exit here: process will continue but logs won't be available. -} - -if ([string]::IsNullOrWhitespace($SampleName)) -{ - $SampleName = (Resolve-Path $Directory).Path.Replace((Get-Location), '').Replace('\', '.').Trim('.').ToLower() -} - -$solutionFile = Get-ChildItem -Path $Directory -Filter *.sln | Select-Object -ExpandProperty FullName -First 1 - -if ($null -eq $solutionFile) -{ - Write-Warning "`u{274C} A solution could not be found under $Directory" - exit 1 -} - -$configurationIsSupported = $false -$inSolutionConfigurationPlatformsSection = $false -foreach ($line in Get-Content -Path $solutionFile) -{ - if (-not $inSolutionConfigurationPlatformsSection -and $line -match "\s*GlobalSection\(SolutionConfigurationPlatforms\).*") - { - $inSolutionConfigurationPlatformsSection = $true; - continue; - } - elseif ($line -match "\s*EndGlobalSection.*") - { - $inSolutionConfigurationPlatformsSection = $false; - continue; - } - - if ($inSolutionConfigurationPlatformsSection) - { - [regex]$regex = ".*=\s*(?<ConfigString>(?<Configuration>.*)\|(?<Platform>.*))\s*" - $match = $regex.Match($line) - if ([string]::IsNullOrWhiteSpace($match.Groups["ConfigString"].Value) -or [string]::IsNullOrWhiteSpace($match.Groups["Platform"].Value)) - { - Write-Warning "Could not parse configuration entry $line from file $solutionFile." - continue; - } - if ($match.Groups["Configuration"].Value.Trim() -eq $Configuration -and $match.Groups["Platform"].Value.Trim() -eq $Platform) - { - $configurationIsSupported = $true; - } - } -} - -if (-not $configurationIsSupported) -{ - Write-Verbose "[$SampleName] `u{23E9} Skipped. Configuration $Configuration|$Platform not supported." - exit 3 -} - -Write-Verbose "Building Sample: $SampleName; Configuration: $Configuration; Platform: $Platform {" - -$myexit=0 - -# -# Let us build up to three times (0th, 1st, and 2nd attempt). -# If we succeed at first, then it is a success. -# If we fail at first, but succeed at either of next two attempts, then it is a sporadic failure. -# If we even at third attempt fail, then it is a true failure. -# -for ($i = 0; $i -lt 3; $i++) -{ - $binLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.binlog" - $errorLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.err" - $warnLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.wrn" - $OutLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.out" - - msbuild $solutionFile -clp:Verbosity=m -t:rebuild -property:Configuration=$Configuration -property:Platform=$Platform -p:TargetVersion=Windows10 -p:InfVerif_AdditionalOptions="$InfVerif_AdditionalOptions" -warnaserror -binaryLogger:LogFile=$binLogFilePath`;ProjectImports=None -flp1:errorsonly`;logfile=$errorLogFilePath -flp2:WarningsOnly`;logfile=$warnLogFilePath -noLogo > $OutLogFilePath - if ($null -ne $env:WDS_WipeOutputs) - { - Write-Verbose ("WipeOutputs: " + $Directory + " " + (((Get-Volume (Get-Item ".").PSDrive.Name).SizeRemaining / 1GB))) - Get-ChildItem -path $Directory -Recurse -Include x64 | Remove-Item -Recurse - Get-ChildItem -path $Directory -Recurse -Include arm64 | Remove-Item -Recurse - } - if ($LASTEXITCODE -eq 0) - { - # We succeeded building. - # If it was at a later attempt, let the caller know with a different exit code. - if ($i -eq 0) - { - $myexit = 0 - } - else - { - $myexit = 2 - } - # Remove binlog on success to save space; keep otherwise to diagnose issues. - Remove-Item $binLogFilePath - break; - } - else - { - # We failed building. - # Let us sleep for a bit. - # Then let the while loop do its thing and re-run. - Start-Sleep 1 - if ($Verbose) - { - Write-Warning "`u{274C} Build failed. Retrying to see if sporadic..." - } - } -} - -if ($myexit -eq 1) -{ - if ($Verbose) - { - Write-Warning "`u{274C} Build failed. Log available at $errorLogFilePath" - } - exit 1 -} - -if ($myexit -eq 2) -{ - if ($Verbose) - { - Write-Warning "`u{274C} Build sporadically failed. Log available at $errorLogFilePath" - } - exit 2 -} - -Write-Verbose "Building Sample: $SampleName; Configuration: $Configuration; Platform: $Platform }" diff --git a/Build-SampleSet.ps1 b/Build-SampleSet.ps1 deleted file mode 100644 index 8638d517..00000000 --- a/Build-SampleSet.ps1 +++ /dev/null @@ -1,375 +0,0 @@ -[CmdletBinding()] -param( - [hashtable]$SampleSet, - [string[]]$Configurations = @(if ([string]::IsNullOrEmpty($env:WDS_Configuration)) { "Debug" } else { $env:WDS_Configuration }), - [string[]]$Platforms = @(if ([string]::IsNullOrEmpty($env:WDS_Platform)) { "x64" } else { $env:WDS_Platform }), - $LogFilesDirectory = (Get-Location), - [string]$ReportFileName = $(if ([string]::IsNullOrEmpty($env:WDS_ReportFileName)) { "_overview" } else { $env:WDS_ReportFileName }), - [int]$ThrottleLimit = 0 -) - -$root = Get-Location - -# launch developer powershell (if necessary to prevent multiple developer sessions) -if (-not $env:VSCMD_VER) { - Import-Module (Resolve-Path "$env:ProgramFiles\Microsoft Visual Studio\2022\*\Common7\Tools\Microsoft.VisualStudio.DevShell.dll") - Enter-VsDevShell -VsInstallPath (Resolve-Path "$env:ProgramFiles\Microsoft Visual Studio\2022\*") - Set-Location $root -} - -$ThrottleFactor = 5 -$LogicalProcessors = (Get-CIMInstance -Class 'CIM_Processor' -Verbose:$false).NumberOfLogicalProcessors - -if ($ThrottleLimit -eq 0) { - $ThrottleLimit = $ThrottleFactor * $LogicalProcessors -} - -$Verbose = $false -if ($PSBoundParameters.ContainsKey('Verbose')) { - $Verbose = $PsBoundParameters.Get_Item('Verbose') -} - -New-Item -ItemType Directory -Force -Path $LogFilesDirectory | Out-Null -$reportFilePath = Join-Path $LogFilesDirectory "$ReportFileName.htm" -$reportCsvFilePath = Join-Path $LogFilesDirectory "$ReportFileName.csv" - - -Remove-Item -Recurse -Path $LogFilesDirectory 2>&1 | Out-Null -New-Item -ItemType Directory -Force -Path $LogFilesDirectory | Out-Null - -$oldPreference = $ErrorActionPreference -$ErrorActionPreference = "stop" -try { - # Check that msbuild can be called before trying anything. - Get-Command "msbuild" | Out-Null -} -catch { - Write-Host "`u{274C} msbuild cannot be called from current environment. Check that msbuild is set in current path (for example, that it is called from a Visual Studio developer command)." - Write-Error "msbuild cannot be called from current environment." - exit 1 -} -finally { - $ErrorActionPreference = $oldPreference -} - -# -# Determine build environment: 'GitHub', 'NuGet', 'EWDK', or 'WDK'. -# Determine build number (used for exclusions based on build number). Five digits. Say, '22621'. -# Determine NuGet package version (if applicable). -# -$build_environment="" -$build_number=0 -$nuget_package_version=0 -# -# In Github we build using NuGet. -# -if ($env:GITHUB_REPOSITORY) { - $build_environment="GitHub" - $nuget_package_version=([regex]'(?<=x64\.)(\d+\.)(\d+\.)(\d+\.)(\d+)').Matches((Get-Childitem .\packages\*WDK.x64* -Name)).Value - $build_number=$nuget_package_version.split('.')[2] -} -# -# WDK NuGet will require presence of a folder 'packages'. The version is sourced from repo .\Env-Vars.ps1. -# -# Hack: If user has hydrated nuget packages, then use those. That will be indicated by presence of a folder named '.\packages'. -# Further, we need to test that the directory has been hydrated using '.\packages\*'. -# -elseif(Test-Path(".\packages\*")) { - $build_environment=("NuGet") - $nuget_package_version=([regex]'(?<=x64\.)(\d+\.)(\d+\.)(\d+\.)(\d+)').Matches((Get-Childitem .\packages\*WDK.x64* -Name)).Value - $build_number=$nuget_package_version.split('.')[2] -} -# -# EWDK sets environment variable BuildLab. For example 'ni_release_svc_prod1.22621.2428'. -# -elseif($env:BuildLab -match '(?<branch>[^.]*).(?<build>[^.]*).(?<qfe>[^.]*)') { - $build_environment=("EWDK."+$Matches.branch+"."+$Matches.build+"."+$Matches.qfe) - $build_number=$Matches.build -} -# -# WDK sets environment variable UCRTVersion. For example '10.0.22621.0'. -# -elseif ($env:UCRTVersion -match '10.0.(?<build>.*).0') { - $build_environment="WDK" - $build_number=$Matches.build -} -else { - - # Dump all environment variables so as to help debug error: - Write-Output "Environment variables {" - Get-ChildItem env:* | Sort-Object name - Write-Output "Environment variables }" - - Write-Error "Could not determine build environment." - exit 1 -} - -# Determine WDK Visual Studio Component version -# -# Be lenient with EWDK builds that do not include the component information -if ($build_environment -match '^EWDK') { - $wdk_vs_component_ver = "(WDK Visual Studio Component Version is not included for EWDK builds)" -} else { - # Get the WDK extension version from installed packages - $wdk_vs_component_ver = Get-ChildItem "${env:ProgramData}\Microsoft\VisualStudio\Packages\Microsoft.Windows.DriverKit,version=*" -ErrorAction SilentlyContinue - if (-not $wdk_vs_component_ver) { - Write-Error "WDK Visual Studio Component version not found. Please ensure the WDK Component is installed." - exit 1 - } - $wdk_vs_component_ver = [regex]::Match($wdk_vs_component_ver.Name, '(\d+\.){3}\d+').Value -} - -# -# -# InfVerif_AdditionalOptions -# -# Samples must build cleanly and even without warnings. -# -# An exception is for infverif where specific warnings are acceptable. Those -# specific warnings indicates issues intentially present in the samples, that -# anyone that clones the samples must fix as part of productizing a driver. -# -# In 22621 those warnings are: /sw1284 /sw1285 /sw1293 /sw2083 /sw2086 -# -# After 22621 those warnings are put under a common flag: /samples -# -$InfVerif_AdditionalOptions=($build_number -le 22621 ? "/sw1284 /sw1285 /sw1293 /sw2083 /sw2086" : "/samples") - -# -# Determine exclusions. -# -# Exclusions are loaded from .\exclusions.csv. -# Each line has form: -# Path,Configurations,MinBuild,MaxBuild,Reason -# Where: -# Path: Is the path to folder containing solution(s) using backslashes. For example: 'audio\acx\samples\audiocodec\driver' . -# Configurations: Are the configurations to exclude. For example: '*|arm64' . -# MinBuild: Is the minimum WDK/EWDK build number the exclusion is applicable for. For example: '22621' . -# MaxBuild: Is the maximum WDK/EWDK build number the exclusion is applicable for. For example: '26031' . -# Reason: Is plain text documenting the reason for the exclusion. For example: 'error C1083: Cannot open include file: 'acx.h': No such file or directory' . -# -$exclusionConfigurations = @{} -$exclusionReasons = @{} -Import-Csv 'exclusions.csv' | ForEach-Object { - $excluded_driver=$_.Path.Replace($root, '').Trim('\').Replace('\', '.').ToLower() - $excluded_configurations=($_.configurations -eq '' ? '*' : $_.configurations) - $excluded_minbuild=($_.MinBuild -eq '' ? 00000 : $_.MinBuild) - $excluded_maxbuild=($_.MaxBuild -eq '' ? 99999 : $_.MaxBuild) - if (($excluded_minbuild -le $build_number) -and ($build_number -le $excluded_maxbuild) ) - { - $exclusionConfigurations[$excluded_driver] = $excluded_configurations - $exclusionReasons[$excluded_driver] = $_.Reason - Write-Verbose "Exclusion.csv entry applied for '$excluded_driver' for configuration '$excluded_configurations'." - } - else - { - Write-Verbose "Exclusion.csv entry not applied for '$excluded_driver' due to build number." - } -} - -$jresult = @{ - SolutionsBuilt = 0 - SolutionsSucceeded = 0 - SolutionsExcluded = 0 - SolutionsUnsupported = 0 - SolutionsFailed = 0 - SolutionsSporadic = 0 - Results = @() - FailSet = @() - lock = [System.Threading.Mutex]::new($false) -} - -$SolutionsTotal = $sampleSet.Count * $Configurations.Count * $Platforms.Count - -Write-Output "WDK Build Environment: $build_environment" -Write-Output "WDK Build Number: $build_number" -if (($build_environment -eq "GitHub") -or ($build_environment -eq "NuGet")) { -Write-Output "WDK Nuget Version: $nuget_package_version" -} -Write-Output "WDK Visual Studio Component Version: $wdk_vs_component_ver" -Write-Output "Samples: $($sampleSet.Count)" -Write-Output "Configurations: $($Configurations.Count) ($Configurations)" -Write-Output "Platforms: $($Platforms.Count) ($Platforms)" -Write-Output "InfVerif_AdditionalOptions: $InfVerif_AdditionalOptions" -Write-Output "Combinations: $SolutionsTotal" -Write-Output "LogicalProcessors: $LogicalProcessors" -Write-Output "ThrottleFactor: $ThrottleFactor" -Write-Output "ThrottleLimit: $ThrottleLimit" -Write-Output "WDS_WipeOutputs: $env:WDS_WipeOutputs" -Write-Output "Disk Remaining (GB): $(((Get-Volume ((Get-Item ".").PSDrive.Name)).SizeRemaining) / 1GB)" -Write-Output "" -Write-Output "T: Combinations" -Write-Output "B: Built" -Write-Output "R: Build is running currently" -Write-Output "P: Build is pending an available build slot" -Write-Output "" -Write-Output "S: Built and result was 'Succeeded'" -Write-Output "E: Built and result was 'Excluded'" -Write-Output "U: Built and result was 'Unsupported' (Platform and Configuration combination)" -Write-Output "F: Built and result was 'Failed'" -Write-Output "O: Built and result was 'Sporadic'" -Write-Output "" -Write-Output "Building all combinations..." - -$Results = @() - -$sw = [Diagnostics.Stopwatch]::StartNew() - -$SampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel { - $LogFilesDirectory = $using:LogFilesDirectory - $exclusionConfigurations = $using:exclusionConfigurations - $exclusionReasons = $using:exclusionReasons - $Configurations = $using:Configurations - $Platforms = $using:Platforms - $InfVerif_AdditionalOptions = $using:InfVerif_AdditionalOptions - $Verbose = $using:Verbose - - $sampleName = $_.Key - $directory = $_.Value - - $ResultElement = new-object psobject - Add-Member -InputObject $ResultElement -MemberType NoteProperty -Name Sample -Value "$sampleName" - - foreach ($configuration in $Configurations) { - foreach ($platform in $Platforms) { - $thisunsupported = 0 - $thisfailed = 0 - $thissporadic = 0 - $thisexcluded = 0 - $thissucceeded = 0 - $thisresult = "Not run" - $thisfailset = @() - $thissporadicset = @() - - if ($exclusionConfigurations.ContainsKey($sampleName) -and ($exclusionConfigurations[$sampleName].Split(';') | Where-Object { "$configuration|$platform" -like $_ })) { - # Verbose - Write-Verbose "[$sampleName $configuration|$platform] `u{23E9} Excluded and skipped. Reason: $($exclusionReasons[$sampleName])" - $thisexcluded += 1 - $thisresult = "Excluded" - } - else { - .\Build-Sample -Directory $directory -SampleName $sampleName -LogFilesDirectory $LogFilesDirectory -Configuration $configuration -Platform $platform -InfVerif_AdditionalOptions $InfVerif_AdditionalOptions -Verbose:$Verbose - if ($LASTEXITCODE -eq 0) { - $thissucceeded += 1 - $thisresult = "Succeeded" - } - elseif ($LASTEXITCODE -eq 1) { - $thisfailset += "$sampleName $configuration|$platform" - $thisfailed += 1 - $thisresult = "Failed" - } - elseif ($LASTEXITCODE -eq 2) { - $thissporadicset += "$sampleName $configuration|$platform" - $thissporadic += 1 - $thisresult = "Sporadic" - } - else { - # ($LASTEXITCODE -eq 3) - $thisunsupported += 1 - $thisresult = "Unsupported" - } - } - Add-Member -InputObject $ResultElement -MemberType NoteProperty -Name "$configuration|$platform" -Value "$thisresult" - - $null = ($using:jresult).lock.WaitOne() - try { - ($using:jresult).SolutionsBuilt += 1 - ($using:jresult).SolutionsSucceeded += $thissucceeded - ($using:jresult).SolutionsExcluded += $thisexcluded - ($using:jresult).SolutionsUnsupported += $thisunsupported - ($using:jresult).SolutionsFailed += $thisfailed - ($using:jresult).SolutionsSporadic += $thissporadic - ($using:jresult).FailSet += $thisfailset - ($using:jresult).SporadicSet += $thissporadicset - $SolutionsTotal = $using:SolutionsTotal - $ThrottleLimit = $using:ThrottleLimit - $SolutionsBuilt = ($using:jresult).SolutionsBuilt - $SolutionsRemaining = $SolutionsTotal - $SolutionsBuilt - $SolutionsRunning = if ($SolutionsRemaining -ge $ThrottleLimit) { $ThrottleLimit } else { $SolutionsRemaining } - $SolutionsPending = if ($SolutionsRemaining -ge $ThrottleLimit) { ($SolutionsRemaining - $ThrottleLimit) } else { 0 } - $SolutionsBuiltPercent = [Math]::Round(100 * ($SolutionsBuilt / $using:SolutionsTotal)) - $TBRP = "T:" + ($SolutionsTotal) + "; B:" + (($using:jresult).SolutionsBuilt) + "; R:" + ($SolutionsRunning) + "; P:" + ($SolutionsPending) - $rstr = "S:" + (($using:jresult).SolutionsSucceeded) + "; E:" + (($using:jresult).SolutionsExcluded) + "; U:" + (($using:jresult).SolutionsUnsupported) + "; F:" + (($using:jresult).SolutionsFailed) + "; O:" + (($using:jresult).SolutionsSporadic) - Write-Progress -Activity "Building combinations" -Status "$SolutionsBuilt of $using:SolutionsTotal combinations built ($SolutionsBuiltPercent%) | $TBRP | $rstr" -PercentComplete $SolutionsBuiltPercent - } - finally { - ($using:jresult).lock.ReleaseMutex() - } - } - } - $null = ($using:jresult).lock.WaitOne() - try { - ($using:jresult).Results += $ResultElement - } - finally { - ($using:jresult).lock.ReleaseMutex() - } -} - -$sw.Stop() - -Write-Output "" - -if ($jresult.FailSet.Count -gt 0) { - Write-Output "Some combinations were built with errors:" - $jresult.FailSet = $jresult.FailSet | Sort-Object - foreach ($failedSample in $jresult.FailSet) { - $failedSample -match "^(.*) (\w*)\|(\w*)$" | Out-Null - $failName = $Matches[1] - $failConfiguration = $Matches[2] - $failPlatform = $Matches[3] - Write-Output "Build errors in Sample $failName; Configuration: $failConfiguration; Platform: $failPlatform {" - Get-Content "$LogFilesDirectory\$failName.$failConfiguration.$failPlatform.0.err" | Write-Output - Write-Output "} $failedSample" - } - Write-Error "Some combinations were built with errors." - Write-Output "" -} - -if ($jresult.SporadicSet.Count -gt 0) { - Write-Output "Some combinations were built with sporadic error:" - $jresult.SporadicSet = $jresult.SporadicSet | Sort-Object - foreach ($sporadicSample in $jresult.SporadicSet) { - $sporadicSample -match "^(.*) (\w*)\|(\w*)$" | Out-Null - $sporadicName = $Matches[1] - $sporadicConfiguration = $Matches[2] - $sporadicPlatform = $Matches[3] - Write-Output "Build sporadic errors in Sample $sporadicName; Configuration: $sporadicConfiguration; Platform: $sporadicPlatform {" - Get-Content "$LogFilesDirectory\$sporadicName.$sporadicConfiguration.$sporadicPlatform.0.err" | Write-Output - Write-Output "} $sporadicSample" - } - Write-Error "Some combinations were built with sporadic errors." - Write-Output "" -} - -# Display timer statistics to host -$min = $sw.Elapsed.Minutes -$seconds = $sw.Elapsed.Seconds - -$SolutionsSucceeded = $jresult.SolutionsSucceeded -$SolutionsExcluded = $jresult.SolutionsExcluded -$SolutionsUnsupported = $jresult.SolutionsUnsupported -$SolutionsFailed = $jresult.SolutionsFailed -$SolutionsSporadic = $jresult.SolutionsSporadic -$Results = $jresult.Results - -Write-Output "Built all combinations." -Write-Output "" -Write-Output "Elapsed time: $min minutes, $seconds seconds." -Write-Output ("Disk Remaining (GB): " + (((Get-Volume (Get-Item ".").PSDrive.Name).SizeRemaining / 1GB))) -Write-Output ("Samples: " + $sampleSet.Count) -Write-Output ("Configurations: " + $Configurations.Count + " (" + $Configurations + ")") -Write-Output ("Platforms: " + $Platforms.Count + " (" + $Platforms + ")") -Write-Output "Combinations: $SolutionsTotal" -Write-Output "Succeeded: $SolutionsSucceeded" -Write-Output "Excluded: $SolutionsExcluded" -Write-Output "Unsupported: $SolutionsUnsupported" -Write-Output "Failed: $SolutionsFailed" -Write-Output "Sporadic: $SolutionsSporadic" -Write-Output "Log files directory: $LogFilesDirectory" -Write-Output "Overview report: $reportFilePath" -Write-Output "" - -$Results | Sort-Object { $_.Sample } | ConvertTo-Csv | Out-File $reportCsvFilePath -$Results | Sort-Object { $_.Sample } | ConvertTo-Html -Title "Overview" | Out-File $reportFilePath -Invoke-Item $reportFilePath diff --git a/Build-Samples.ps1 b/Build-Samples.ps1 new file mode 100644 index 00000000..e0b1a6b3 --- /dev/null +++ b/Build-Samples.ps1 @@ -0,0 +1,781 @@ +<# +.SYNOPSIS + Builds driver samples from a sample list file with parallel execution and exclusion support. + +.DESCRIPTION + This is the main build orchestrator for driver samples. It performs these steps: + + 1. Ensures a developer build environment (VS DevShell or EWDK) is active + 2. Discovers samples via ListAllSamples.ps1 (or uses the -Samples parameter if provided) + 3. Resolves the build environment (auto-detected or forced via -RunMode) and build number + 4. Loads exclusions from exclusions.csv (supports wildcard paths) + 5. Builds all non-excluded sample/configuration/platform combinations in parallel + 6. Generates CSV and HTML overview reports + + Requires PowerShell 7+ (uses ForEach-Object -Parallel). + + +.PARAMETER Samples + Optional array of specific sample names or wildcard patterns to build. Supports + wildcards (e.g. 'tools.*', 'audio.*') which are matched against all discovered + samples. When omitted, all samples are discovered dynamically via ListAllSamples.ps1. + +.PARAMETER Configurations + Build configurations (e.g. 'Debug','Release'). Defaults to $env:WDS_Configuration or + ('Debug','Release'). + +.PARAMETER Platforms + Build platforms (e.g. 'x64','arm64'). Defaults to $env:WDS_Platform or ('x64','arm64'). + +.PARAMETER NtTargetVersion + The _NT_TARGET_VERSION value - the WDK library version the driver links against + ("OS version of libraries"). Accepts the Windows build-number form '10.0.<build>' or the + short '<build>' tag (e.g. '10.0.28000' or '28000'). The valid values are auto-discovered + from the active WDK's DriverGeneral.xml rule (see Get-NtTargetVersions.ps1), so a new WDK + version is picked up with no script change. Defaults to $env:WDS_NtTargetVersion, or the + latest discovered version when unset. + +.PARAMETER LogFilesDirectory + Directory for build log files. Defaults to _logs in the current directory. + +.PARAMETER ReportFileName + Base name for the report files (without extension). Defaults to $env:WDS_ReportFileName + or '_overview'. + +.PARAMETER InfOptions + Additional InfVerif options (e.g. '/samples', '/msft'). If not provided, determined + automatically based on the WDK build number. + +.PARAMETER RunMode + Selects the build environment mode. Valid values: Auto, WDK, NuGet, EWDK. + Defaults to 'Auto', which detects the environment automatically (NuGet → EWDK → WDK). + +.PARAMETER ThrottleLimit + Maximum parallel build jobs. Defaults to 5 x logical processors. + +.EXAMPLE + .\Build-Samples + + Discovers all samples via ListAllSamples.ps1 and builds them with default settings. + +.EXAMPLE + .\Build-Samples -Samples 'audio.acx.samples.audiocodec.driver','usb.kmdf_fx2' -Configurations 'Debug' -Platforms 'x64' + + Builds specific samples for a single configuration and platform. + +.EXAMPLE + .\Build-Samples -Samples 'tools.*' + + Builds all samples whose name matches the wildcard pattern 'tools.*'. + +.EXAMPLE + .\Build-Samples -ThrottleLimit 8 + + Discovers all samples and builds them with limited parallelism. + +.EXAMPLE + .\Build-Samples -RunMode WDK + + Forces WDK mode regardless of environment variables. + +.EXAMPLE + .\Build-Samples -NtTargetVersion 10.0.22000 + + Builds all samples linking against the 10.0.22000 library set instead of the latest. +#> + +#Requires -Version 7.0 + +[CmdletBinding()] +param( + [string[]]$Samples, + [string[]]$Configurations = @(if ([string]::IsNullOrEmpty($env:WDS_Configuration)) { ('Debug', 'Release') } else { $env:WDS_Configuration }), + [string[]]$Platforms = @(if ([string]::IsNullOrEmpty($env:WDS_Platform)) { ('x64', 'arm64') } else { $env:WDS_Platform }), + # _NT_TARGET_VERSION = the WDK library version the driver links against. Valid values are + # auto-discovered from the WDK (Get-NtTargetVersions.ps1); empty = the latest discovered. + [string]$NtTargetVersion = $env:WDS_NtTargetVersion, + [string]$LogFilesDirectory = (Join-Path (Get-Location) "_logs"), + [string]$ReportFileName = $(if ([string]::IsNullOrEmpty($env:WDS_ReportFileName)) { "_overview" } else { $env:WDS_ReportFileName }), + [string]$InfOptions, + [ValidateSet('Auto', 'WDK', 'NuGet', 'EWDK')] + [string]$RunMode = 'Auto', + [int]$ThrottleLimit = 0 +) + +# ============================================================================= +# Helper Functions +# ============================================================================= + +. (Join-Path $PSScriptRoot 'BuildEnvironment.ps1') + +function Import-SampleExclusions { + <# + .SYNOPSIS + Loads exclusions.csv and returns exclusion objects applicable to the current build. + .DESCRIPTION + Each returned exclusion has: + - Pattern: dot-separated path (may contain wildcards, e.g. 'general.*') + - Configurations: semicolon-separated config|platform patterns (or '*' for all) + - Reason: human-readable explanation + + A row is only returned when ALL of the following match the current build: + - its [MinBuild, MaxBuild] range includes the given build number, and + - its [MinNtTargetVersion, MaxNtTargetVersion] range includes the current + _NT_TARGET_VERSION build number (e.g. 22000 parsed from '10.0.22000'). + Rows outside either range are skipped; blank range bounds mean unbounded. + .NOTES + CSV format: Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason + Example row: network\wlan\wdi,*,26100,,,,"failure introduced in VS17.14" + NT-version-specific: somepath,*,,,,22621,"needs an API newer than the 10.0.22621 library" + #> + param( + [string]$CsvPath, + [int]$BuildNumber, + [string]$NtTargetVersion + ) + + if (-not (Test-Path $CsvPath)) { + Write-Warning "Exclusions file not found: $CsvPath. No exclusions will be applied." + return @() + } + + # The _NT_TARGET_VERSION param is the friendly build-number form (e.g. '10.0.22000'); + # take its last dotted component for numeric range comparisons. An empty value (or + # 'latest') means the newest libraries, so no NT-version-scoped row applies. + $ntBuild = if ([string]::IsNullOrWhiteSpace($NtTargetVersion) -or $NtTargetVersion -eq 'latest') { + [int]::MaxValue + } + else { + [int]($NtTargetVersion -replace '.*\.', '') + } + + $exclusions = [System.Collections.ArrayList]::new() + Import-Csv $CsvPath | ForEach-Object { + $pattern = $_.Path.Trim('\').Replace('\', '.').ToLower() + $configs = if ([string]::IsNullOrWhiteSpace($_.Configurations)) { '*' } else { $_.Configurations } + $minBuild = if ([string]::IsNullOrWhiteSpace($_.MinBuild)) { 0 } else { [int]$_.MinBuild } + $maxBuild = if ([string]::IsNullOrWhiteSpace($_.MaxBuild)) { 99999 } else { [int]$_.MaxBuild } + # Min/MaxNtTargetVersion columns are optional; blank or missing means "all NT versions". + $minNt = if ([string]::IsNullOrWhiteSpace($_.MinNtTargetVersion)) { 0 } else { [int]$_.MinNtTargetVersion } + $maxNt = if ([string]::IsNullOrWhiteSpace($_.MaxNtTargetVersion)) { [int]::MaxValue } else { [int]$_.MaxNtTargetVersion } + + # _NT_TARGET_VERSION is constant for the whole run, so (like the build number) filter + # these rows out here at load time. + if ($ntBuild -lt $minNt -or $ntBuild -gt $maxNt) { + Write-Verbose "Exclusion skipped: '$pattern' - _NT_TARGET_VERSION $ntBuild outside [$minNt, $maxNt]" + } + elseif ($minBuild -le $BuildNumber -and $BuildNumber -le $maxBuild) { + [void]$exclusions.Add([PSCustomObject]@{ + Pattern = $pattern + Configurations = $configs + Reason = $_.Reason + }) + Write-Verbose "Exclusion applied: '$pattern' configs='$configs' ntRange=[$minNt,$maxNt] reason='$($_.Reason)'" + } + else { + Write-Verbose "Exclusion skipped: '$pattern' - build $BuildNumber outside [$minBuild, $maxBuild]" + } + } + + return $exclusions.ToArray() +} + +function Get-DiskFreeGB { + <# + .SYNOPSIS Returns free disk space in GB for the current drive, or 'N/A' on error. + #> + try { + return [math]::Round((Get-Volume (Get-Item '.').PSDrive.Name).SizeRemaining / 1GB, 1) + } + catch { + return 'N/A' + } +} + +function Build-SingleSample { + <# + .SYNOPSIS + Builds a single sample directory for one configuration/platform combination. + .DESCRIPTION + Locates the .sln in the given directory, verifies the configuration|platform is + supported, then invokes msbuild with up to 3 attempts (to detect sporadic failures). + .OUTPUTS + Returns an integer exit code: + 0 = succeeded on first attempt + 1 = failed after all retries + 2 = sporadic (failed first, succeeded on retry) + 3 = unsupported configuration/platform + #> + param( + [string]$Directory, + [string]$SampleName, + [string]$Configuration = 'Debug', + [string]$Platform = 'x64', + [string]$NtTargetVersionCode, + [string]$InfVerif_AdditionalOptions = '/samples', + [string]$LogFilesDirectory = (Get-Location), + [bool]$Verbose = $false + ) + + if (-not (Test-Path -Path $Directory -PathType Container)) { + Write-Warning "`u{274C} A valid directory could not be found under $Directory" + return 1 + } + + New-Item -ItemType Directory -Force -Path $LogFilesDirectory | Out-Null + + if ([string]::IsNullOrWhiteSpace($SampleName)) { + $SampleName = (Resolve-Path $Directory).Path.Replace((Get-Location), '').Replace('\', '.').Trim('.').ToLower() + } + + $solutionFile = Get-ChildItem -Path $Directory -Filter *.sln | + Select-Object -ExpandProperty FullName -First 1 + + if ($null -eq $solutionFile) { + Write-Warning "`u{274C} A solution could not be found under $Directory" + return 1 + } + + # --- Check whether the solution supports the requested configuration|platform --- + $configurationIsSupported = $false + $inSolutionConfigurationPlatformsSection = $false + foreach ($line in Get-Content -Path $solutionFile) { + if (-not $inSolutionConfigurationPlatformsSection -and + $line -match '\s*GlobalSection\(SolutionConfigurationPlatforms\).*') { + $inSolutionConfigurationPlatformsSection = $true + continue + } + elseif ($line -match '\s*EndGlobalSection.*') { + $inSolutionConfigurationPlatformsSection = $false + continue + } + + if ($inSolutionConfigurationPlatformsSection) { + [regex]$regex = '.*=\s*(?<ConfigString>(?<Configuration>.*)\|(?<Platform>.*))\s*' + $match = $regex.Match($line) + if ([string]::IsNullOrWhiteSpace($match.Groups['ConfigString'].Value) -or + [string]::IsNullOrWhiteSpace($match.Groups['Platform'].Value)) { + Write-Warning "Could not parse configuration entry $line from file $solutionFile." + continue + } + if ($match.Groups['Configuration'].Value.Trim() -eq $Configuration -and + $match.Groups['Platform'].Value.Trim() -eq $Platform) { + $configurationIsSupported = $true + } + } + } + + if (-not $configurationIsSupported) { + Write-Verbose "[$SampleName] `u{23E9} Skipped. Configuration $Configuration|$Platform not supported." + return 3 + } + + Write-Verbose "Building Sample: $SampleName; Configuration: $Configuration; Platform: $Platform {" + + $myexit = 1 + + # Build up to three times (0th, 1st, and 2nd attempt). + # Succeed on 1st -> success (0) + # Fail 1st, succeed on retry -> sporadic (2) + # Fail all three -> failure (1) + for ($i = 0; $i -lt 3; $i++) { + $binLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.binlog" + $errorLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.err" + $warnLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.wrn" + $outLogFilePath = "$LogFilesDirectory\$SampleName.$Configuration.$Platform.$i.out" + + msbuild $solutionFile ` + -clp:Verbosity=m -t:rebuild ` + -property:Configuration=$Configuration ` + -property:Platform=$Platform ` + -p:TargetVersion=Windows10 ` + -p:_NT_TARGET_VERSION=$NtTargetVersionCode ` + -p:InfVerif_AdditionalOptions="$InfVerif_AdditionalOptions" ` + -warnaserror ` + -binaryLogger:LogFile=$binLogFilePath`;ProjectImports=None ` + -flp1:errorsonly`;logfile=$errorLogFilePath ` + -flp2:WarningsOnly`;logfile=$warnLogFilePath ` + -noLogo > $outLogFilePath + + if ($null -ne $env:WDS_WipeOutputs) { + Write-Verbose ("WipeOutputs: $Directory " + (((Get-Volume (Get-Item '.').PSDrive.Name).SizeRemaining / 1GB))) + Get-ChildItem -Path $Directory -Recurse -Include x64 | Remove-Item -Recurse + Get-ChildItem -Path $Directory -Recurse -Include arm64 | Remove-Item -Recurse + } + + if ($LASTEXITCODE -eq 0) { + $myexit = if ($i -eq 0) { 0 } else { 2 } + # Remove binlog on success to save space; keep otherwise to diagnose issues. + Remove-Item $binLogFilePath + break + } + else { + Start-Sleep 1 + if ($Verbose) { + Write-Warning "`u{274C} Build failed. Retrying to see if sporadic..." + } + } + } + + if ($myexit -eq 1 -and $Verbose) { + Write-Warning "`u{274C} Build failed. Log available at $errorLogFilePath" + } + if ($myexit -eq 2 -and $Verbose) { + Write-Warning "`u{274C} Build sporadically failed. Log available at $errorLogFilePath" + } + + Write-Verbose "Building Sample: $SampleName; Configuration: $Configuration; Platform: $Platform }" + + return $myexit +} + +# ============================================================================= +# Step 1 - Prepare Build Environment +# ============================================================================= + +$root = (Get-Location).Path +$buildEnv = Resolve-BuildEnvironment -RepoRoot $root -RunMode $RunMode +$buildNumber = $buildEnv.BuildNumber +Assert-MsBuildAvailable + +# ============================================================================= +# Step 2 - Calculate Parallelism +# ============================================================================= + +$throttleFactor = 5 +# Sum across all CPU sockets (Get-CimInstance returns an array on multi-socket systems) +$logicalProcessors = ((Get-CimInstance -Class CIM_Processor -Verbose:$false).NumberOfLogicalProcessors | Measure-Object -Sum).Sum + +if ($ThrottleLimit -eq 0) { + $ThrottleLimit = $throttleFactor * $logicalProcessors +} + +$verbose = $PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose'] + +# ============================================================================= +# Step 3 - Prepare Log Directory +# ============================================================================= + +Remove-Item -Recurse -Path $LogFilesDirectory -ErrorAction SilentlyContinue +New-Item -ItemType Directory -Force -Path $LogFilesDirectory | Out-Null + +$reportHtmlPath = Join-Path $LogFilesDirectory "$ReportFileName.htm" +$reportCsvPath = Join-Path $LogFilesDirectory "$ReportFileName.csv" + +# ============================================================================= +# Step 4 - Load Sample List +# ============================================================================= + +# Always discover the full sample list when patterns contain wildcards, +# or when no -Samples were provided at all. +$hasWildcards = $Samples | Where-Object { $_ -match '[*?]' } + +if (-not $Samples) { + # No filter: discover and build everything. + Write-Verbose "No -Samples provided. Discovering samples via ListAllSamples.ps1..." + $sampleNames = & (Join-Path $PSScriptRoot 'ListAllSamples.ps1') -Verbose:$verbose | + Where-Object { -not [string]::IsNullOrWhiteSpace($_) } +} +elseif ($hasWildcards) { + # One or more entries contain wildcards — discover all, then filter with -like. + Write-Verbose "Wildcard detected in -Samples. Discovering all samples to match patterns..." + $allSamples = & (Join-Path $PSScriptRoot 'ListAllSamples.ps1') -Verbose:$verbose | + Where-Object { -not [string]::IsNullOrWhiteSpace($_) } + $sampleNames = @() + foreach ($pattern in $Samples) { + $matched = $allSamples | Where-Object { $_ -like $pattern } + if ($matched) { + $sampleNames += $matched + } + else { + Write-Warning "Pattern '$pattern' did not match any samples." + } + } + $sampleNames = $sampleNames | Sort-Object -Unique +} +else { + # Exact list passed by the caller — use as-is, sorted alphabetically. + $sampleNames = $Samples | Sort-Object +} + +# Map sample names to directory paths, validating each exists +$sampleSet = [ordered]@{} +$skippedCount = 0 +foreach ($name in $sampleNames) { + $fullPath = Join-Path $root ($name.Replace('.', '\')) + if (Test-Path $fullPath -PathType Container) { + $sampleSet[$name] = $fullPath + } + else { + Write-Warning "Sample directory not found, skipping: $name" + $skippedCount++ + } +} + +if ($sampleSet.Count -eq 0) { + Write-Error "No valid sample directories found. Ensure ListAllSamples.ps1 is available in the repo root." + exit 1 +} + +# ============================================================================= +# Step 5 - Determine InfVerif Options +# ============================================================================= +# +# Samples must build cleanly, but certain InfVerif warnings are acceptable because +# they flag issues intentionally present in samples (to be fixed when productizing). +# <= 22621: suppress individual warnings /sw1284 /sw1285 /sw1293 /sw2083 /sw2086 +# > 22621: these are grouped under /samples +# +if ($InfOptions) { + $infVerifOptions = $InfOptions +} +else { + $infVerifOptions = if ($buildNumber -le 22621) { '/sw1284 /sw1285 /sw1293 /sw2083 /sw2086' } else { '/samples' } +} + +# ============================================================================= +# Step 5b - Resolve _NT_TARGET_VERSION +# ============================================================================= +# +# _NT_TARGET_VERSION selects the WDK library version the driver links against. The valid +# values (and their NTDDI codes) are auto-discovered from the active WDK by +# Get-NtTargetVersions.ps1, so nothing here needs updating when a new WDK version ships. +# msbuild takes the NTDDI code. +$ntVersions = & (Join-Path $PSScriptRoot 'Get-NtTargetVersions.ps1') +if (-not $ntVersions) { + Write-Error "Could not discover any _NT_TARGET_VERSION values from the active WDK." + exit 1 +} +if ([string]::IsNullOrWhiteSpace($NtTargetVersion) -or $NtTargetVersion -eq 'latest') { + $ntSelected = $ntVersions[0] # newest +} +else { + $ntSelected = $ntVersions | Where-Object { $_.Version -eq $NtTargetVersion -or $_.Tag -eq $NtTargetVersion } | Select-Object -First 1 + if (-not $ntSelected) { + Write-Error "Invalid -NtTargetVersion '$NtTargetVersion'. Valid values: $(($ntVersions.Version) -join ', ')" + exit 1 + } +} +$NtTargetVersion = $ntSelected.Version +$ntTargetVersionCode = $ntSelected.Code + +# ============================================================================= +# Step 6 - Load Exclusions +# ============================================================================= + +$exclusions = Import-SampleExclusions -CsvPath (Join-Path $root 'exclusions.csv') -BuildNumber $buildNumber -NtTargetVersion $NtTargetVersion + +# ============================================================================= +# Step 7 - Print Build Plan +# ============================================================================= + +$combinationsTotal = $sampleSet.Count * $Configurations.Count * $Platforms.Count + +Write-Output "" +Write-Output "--- WDK Sample Build Plan ------------------------------------------" +Write-Output " Environment: $($buildEnv.Name)" +Write-Output " Build Number: $buildNumber" +if ($buildEnv.NuGetVersion) { + Write-Output " NuGet Version: $($buildEnv.NuGetVersion)" +} +Write-Output " WDK VS Component: $($buildEnv.WdkVsComponentVersion)" +Write-Output " InfVerif Options: $infVerifOptions" +Write-Output "" +Write-Output " Samples: $($sampleSet.Count) ($skippedCount skipped)" +Write-Output " Configurations: $($Configurations -join ', ')" +Write-Output " Platforms: $($Platforms -join ', ')" +Write-Output " NT Target Ver: $NtTargetVersion ($ntTargetVersionCode)" +Write-Output " Combinations: $combinationsTotal" +Write-Output " Exclusions: $($exclusions.Count)" +Write-Output "" +Write-Output " Parallelism: $ThrottleLimit jobs ($logicalProcessors cores x $throttleFactor)" +Write-Output " Disk Free (GB): $(Get-DiskFreeGB)" +Write-Output " Wipe Outputs: $(-not [string]::IsNullOrEmpty($env:WDS_WipeOutputs))" +Write-Output "--------------------------------------------------------------------" +Write-Output "" +Write-Output "Progress legend:" +Write-Output " T=Total B=Built R=Running P=Pending" +Write-Output " S=Succeeded E=Excluded U=Unsupported F=Failed O=Sporadic" +Write-Output "" +Write-Output "Building all combinations..." + +# ============================================================================= +# Step 8 - Execute Parallel Builds +# ============================================================================= + +# Shared mutable state protected by a Mutex. This is required because +# ForEach-Object -Parallel runs each iteration in a separate runspace, +# so standard .NET locks (Monitor/lock) do not work across runspaces. +$buildState = @{ + Built = 0 + Succeeded = 0 + Excluded = 0 + Unsupported = 0 + Failed = 0 + Sporadic = 0 + Results = @() + FailSet = @() + SporadicSet = @() + Lock = [System.Threading.Mutex]::new($false) +} + +$stopwatch = [Diagnostics.Stopwatch]::StartNew() + +# Capture function definition so it can be reconstructed inside each parallel runspace. +$buildSingleSampleDef = ${function:Build-SingleSample}.ToString() + +$sampleSet.GetEnumerator() | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel { + # --- Import shared state from parent scope --- + $logDir = $using:LogFilesDirectory + $exclusions = $using:exclusions + $configs = $using:Configurations + $platforms = $using:Platforms + $infOpts = $using:infVerifOptions + $ntCode = $using:ntTargetVersionCode + $isVerbose = $using:verbose + $state = $using:buildState + $total = $using:combinationsTotal + $throttle = $using:ThrottleLimit + + # Reconstruct the function inside this parallel runspace + ${function:Build-SingleSample} = $using:buildSingleSampleDef + + $sampleName = $_.Key + $directory = $_.Value + + # Build a result row: one column per configuration|platform combination + $resultRow = [PSCustomObject]@{ Sample = $sampleName } + + foreach ($configuration in $configs) { + foreach ($platform in $platforms) { + $result = 'Not run' + $succeededDelta = 0 + $excludedDelta = 0 + $unsupportedDelta = 0 + $failedDelta = 0 + $sporadicDelta = 0 + $failEntry = $null + $sporadicEntry = $null + + # -- Check exclusions (supports wildcard paths like 'general.*') -- + $exclusionReason = $null + foreach ($excl in $exclusions) { + if ($sampleName -like $excl.Pattern) { + $configKey = "$configuration|$platform" + foreach ($cfgPattern in $excl.Configurations.Split(';')) { + if ($configKey -like $cfgPattern) { + $exclusionReason = $excl.Reason + break + } + } + if ($exclusionReason) { break } + } + } + + if ($exclusionReason) { + Write-Verbose "[$sampleName $configuration|$platform] Excluded: $exclusionReason" + $excludedDelta = 1 + $result = 'Excluded' + } + else { + # -- Build the sample -- + $buildResult = Build-SingleSample ` + -Directory $directory -SampleName $sampleName ` + -LogFilesDirectory $logDir -Configuration $configuration ` + -Platform $platform -NtTargetVersionCode $ntCode ` + -InfVerif_AdditionalOptions $infOpts ` + -Verbose:$isVerbose + + # Return codes from Build-SingleSample: + # 0 = succeeded on first attempt + # 1 = failed after all retries + # 2 = sporadic (failed first, succeeded on retry) + # 3 = unsupported configuration/platform + switch ($buildResult) { + 0 { $succeededDelta = 1; $result = 'Succeeded' } + 1 { $failedDelta = 1; $result = 'Failed'; $failEntry = "$sampleName $configuration|$platform" } + 2 { $sporadicDelta = 1; $result = 'Sporadic'; $sporadicEntry = "$sampleName $configuration|$platform" } + default { $unsupportedDelta = 1; $result = 'Unsupported' } + } + } + + $resultRow | Add-Member -MemberType NoteProperty -Name "$configuration|$platform" -Value $result + + # -- Update shared counters (under lock) -- + $null = $state.Lock.WaitOne() + try { + $state.Built += 1 + $state.Succeeded += $succeededDelta + $state.Excluded += $excludedDelta + $state.Unsupported += $unsupportedDelta + $state.Failed += $failedDelta + $state.Sporadic += $sporadicDelta + if ($failEntry) { $state.FailSet += $failEntry } + if ($sporadicEntry) { $state.SporadicSet += $sporadicEntry } + + # Update progress bar + $built = $state.Built + $remaining = $total - $built + $running = [Math]::Min($remaining, $throttle) + $pending = [Math]::Max($remaining - $throttle, 0) + $pct = [Math]::Round(100 * $built / $total) + + $statusLine = "$built of $total combinations built ($pct%) | " + + "T:$total; B:$built; R:$running; P:$pending | " + + "S:$($state.Succeeded); E:$($state.Excluded); U:$($state.Unsupported); F:$($state.Failed); O:$($state.Sporadic)" + + # Write-Host with carriage return for a single-line progress indicator. + # Write-Progress does not reliably render from -Parallel runspaces. + Write-Host "`rBuilding combinations [$statusLine]" -NoNewline + } + finally { + $state.Lock.ReleaseMutex() + } + } + } + + # Append the completed result row + $null = $state.Lock.WaitOne() + try { + $state.Results += $resultRow + } + finally { + $state.Lock.ReleaseMutex() + } +} + +$stopwatch.Stop() + +# End the progress line +Write-Host "" + +# ============================================================================= +# Step 9 - Report Failures +# ============================================================================= + +Write-Output "" + +if ($buildState.FailSet.Count -gt 0) { + Write-Output "--- Build Failures -------------------------------------------------" + foreach ($entry in ($buildState.FailSet | Sort-Object)) { + if ($entry -match '^(?<name>.*)\s+(?<config>\w+)\|(?<platform>\w+)$') { + $errLog = Join-Path $LogFilesDirectory "$($Matches.name).$($Matches.config).$($Matches.platform).0.err" + Write-Output " [FAIL] $($Matches.name) ($($Matches.config)|$($Matches.platform)):" + if (Test-Path $errLog) { + Get-Content $errLog | ForEach-Object { Write-Output " $_" } + } + else { + Write-Output " (error log not found: $errLog)" + } + } + } + Write-Output "" + Write-Error "Some combinations were built with errors." +} + +if ($buildState.SporadicSet.Count -gt 0) { + Write-Output "--- Sporadic Failures (succeeded on retry) -------------------------" + foreach ($entry in ($buildState.SporadicSet | Sort-Object)) { + if ($entry -match '^(?<name>.*)\s+(?<config>\w+)\|(?<platform>\w+)$') { + $errLog = Join-Path $LogFilesDirectory "$($Matches.name).$($Matches.config).$($Matches.platform).0.err" + Write-Output " [SPORADIC] $($Matches.name) ($($Matches.config)|$($Matches.platform)):" + if (Test-Path $errLog) { + Get-Content $errLog | ForEach-Object { Write-Output " $_" } + } + } + } + Write-Output "" + Write-Error "Some combinations had sporadic build failures." +} + +# ============================================================================= +# Step 10 - Final Summary +# ============================================================================= + +$elapsed = $stopwatch.Elapsed + +Write-Output "--- Build Complete -------------------------------------------------" +Write-Output " Elapsed: $($elapsed.Minutes)m $($elapsed.Seconds)s" +Write-Output " Disk Free (GB): $(Get-DiskFreeGB)" +Write-Output "" +Write-Output " Samples: $($sampleSet.Count)" +Write-Output " Configurations: $($Configurations -join ', ')" +Write-Output " Platforms: $($Platforms -join ', ')" +Write-Output " NT Target Ver: $NtTargetVersion ($ntTargetVersionCode)" +Write-Output " Combinations: $combinationsTotal" +Write-Output "" +Write-Output " Succeeded: $($buildState.Succeeded)" +Write-Output " Excluded: $($buildState.Excluded)" +Write-Output " Unsupported: $($buildState.Unsupported)" +Write-Output " Failed: $($buildState.Failed)" +Write-Output " Sporadic: $($buildState.Sporadic)" +Write-Output "" +Write-Output " Log directory: $LogFilesDirectory" +Write-Output " CSV report: $reportCsvPath" +Write-Output " HTML report: $reportHtmlPath" +Write-Output "--------------------------------------------------------------------" + +# ============================================================================= +# Step 11 - Generate Reports +# ============================================================================= + +$sortedResults = $buildState.Results | Sort-Object { $_.Sample } +$sortedResults | ConvertTo-Csv | Out-File $reportCsvPath +$sortedResults | ConvertTo-Html -Title "WDK Sample Build Overview - _NT_TARGET_VERSION $NtTargetVersion" | Out-File $reportHtmlPath + +# Only open the HTML report interactively (not in CI/automation) +if (-not $env:BUILD_BUILDID -and [Environment]::UserInteractive) { + Invoke-Item $reportHtmlPath +} + +# ============================================================================= +# Step 12 - GitHub Actions job summary (CI only; no-op when run locally) +# ============================================================================= +# When $GITHUB_STEP_SUMMARY is set, emit an easy-to-scan markdown summary for the run +# page: a status header, a counts table, and (if any) a table of failures with the first +# compiler/linker error so problems are obvious without opening the logs. +if ($env:GITHUB_STEP_SUMMARY) { + $icon = if ($buildState.Failed -gt 0) { ':x:' } elseif ($buildState.Sporadic -gt 0) { ':warning:' } else { ':white_check_mark:' } + $cfgLabel = "$($Configurations -join ',')|$($Platforms -join ',')" + + $md = [System.Text.StringBuilder]::new() + [void]$md.AppendLine("## $icon ``$cfgLabel`` · _NT_TARGET_VERSION ``$NtTargetVersion``") + [void]$md.AppendLine() + [void]$md.AppendLine("Environment **$($buildEnv.Name)** · WDK build **$buildNumber** · **$($sampleSet.Count)** samples · $($elapsed.Minutes)m $($elapsed.Seconds)s") + [void]$md.AppendLine() + [void]$md.AppendLine("| :white_check_mark: Succeeded | :x: Failed | :warning: Sporadic | :heavy_minus_sign: Excluded | :grey_question: Unsupported |") + [void]$md.AppendLine("|---:|---:|---:|---:|---:|") + [void]$md.AppendLine("| $($buildState.Succeeded) | $($buildState.Failed) | $($buildState.Sporadic) | $($buildState.Excluded) | $($buildState.Unsupported) |") + [void]$md.AppendLine() + + if ($buildState.FailSet.Count -gt 0) { + [void]$md.AppendLine("<details open><summary><b>:x: $($buildState.FailSet.Count) failed</b></summary>") + [void]$md.AppendLine() + [void]$md.AppendLine("| Sample | Config/Platform | First error |") + [void]$md.AppendLine("|---|---|---|") + foreach ($entry in ($buildState.FailSet | Sort-Object)) { + if ($entry -match '^(?<name>.*)\s+(?<config>\w+)\|(?<platform>\w+)$') { + $fName = $Matches.name; $fConfig = $Matches.config; $fPlatform = $Matches.platform + $errLog = Join-Path $LogFilesDirectory "$fName.$fConfig.$fPlatform.0.err" + $msg = '' + if (Test-Path $errLog) { + $line = Get-Content $errLog | Where-Object { $_ -match ': (error|fatal error) ' } | Select-Object -First 1 + if ($line -match ':\s*((?:fatal )?error\s.+?)\s*\[[^\[]*\]\s*$') { $msg = $Matches[1] } else { $msg = $line } + } + $msg = ("$msg" -replace '\|', '\|').Trim() + if ($msg.Length -gt 180) { $msg = $msg.Substring(0, 177) + '...' } + [void]$md.AppendLine("| ``$fName`` | $fConfig/$fPlatform | $msg |") + } + } + [void]$md.AppendLine("</details>") + [void]$md.AppendLine() + } + + if ($buildState.SporadicSet.Count -gt 0) { + $sp = ($buildState.SporadicSet | Sort-Object | ForEach-Object { "``$_``" }) -join ', ' + [void]$md.AppendLine(":warning: **Sporadic** (passed on retry): $sp") + [void]$md.AppendLine() + } + + $md.ToString() | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append -Encoding utf8 +} diff --git a/BuildEnvironment.ps1 b/BuildEnvironment.ps1 new file mode 100644 index 00000000..bdb90a2e --- /dev/null +++ b/BuildEnvironment.ps1 @@ -0,0 +1,220 @@ +# BuildEnvironment.ps1 +# Helper functions for detecting and initialising the build environment. +# Dot-sourced by Build-Samples.ps1. + +function Get-VsInstallationsWithWdk { + <# + .SYNOPSIS + Returns all Visual Studio installations that have the WDK component installed. + .DESCRIPTION + Uses vswhere.exe (from its fixed install location under Program Files (x86)) to + enumerate VS installations that carry the Microsoft.Windows.DriverKit component. + If vswhere.exe is not found at the expected path the installed VS version is too + old to be supported and the script exits with an error. + #> + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + if (-not (Test-Path $vswhere)) { + Write-Error "vswhere.exe was not found at '$vswhere'. Visual Studio 2017 or later is required." + exit 1 + } + + # Full VS editions install the WDK component as 'Microsoft.Windows.DriverKit', + # while Build Tools uses 'Component.Microsoft.Windows.DriverKit.BuildTools'. + # Query for either so both product types are discovered. + $wdkComponentIds = @('Microsoft.Windows.DriverKit', 'Component.Microsoft.Windows.DriverKit.BuildTools') + $allInstallations = @() + foreach ($componentId in $wdkComponentIds) { + $json = & $vswhere -all -products * -format json -requires $componentId -include packages 2>$null + if ($json) { + $allInstallations += ($json | ConvertFrom-Json) + } + } + # Deduplicate by installationPath in case both components are present + $installations = $allInstallations | Sort-Object -Property installationPath -Unique + return $installations | ForEach-Object { + $wdkPackage = $_.packages | Where-Object { $_.id -in $wdkComponentIds } | Select-Object -First 1 + [PSCustomObject]@{ + DisplayName = $_.displayName + InstallationPath = $_.installationPath + WdkVsComponentVersion = $wdkPackage.version + } + } +} + +function Select-VsInstallation { + <# + .SYNOPSIS + Chooses a Visual Studio installation from the list returned by Get-VsInstallationsWithWdk. + .DESCRIPTION + - 0 found : error + exit + - 1 found : verbose log, return it + - 2+ found : display a numbered menu and prompt the user to choose + #> + param([object[]]$Installations) + + if (-not $Installations -or $Installations.Count -eq 0) { + Write-Error "No Visual Studio installation with the required WDK media was found. Ensure the WDK Visual Studio component is installed." + exit 1 + } + + if ($Installations.Count -eq 1) { + Write-Verbose "Found Visual Studio installation with required WDK media: $($Installations[0].DisplayName) at $($Installations[0].InstallationPath)" + return $Installations[0] + } + + # Multiple installations — let the user choose + Write-Host "" + Write-Host "The following Visual Studio installations were found with the required WDK media:" + for ($i = 0; $i -lt $Installations.Count; $i++) { + Write-Host " [$($i + 1)] $($Installations[$i].DisplayName) — $($Installations[$i].InstallationPath)" + } + Write-Host "" + + do { + $choice = Read-Host "Select the installation to use [1-$($Installations.Count)]" + $index = [int]$choice - 1 + } while ($index -lt 0 -or $index -ge $Installations.Count) + + return $Installations[$index] +} + +function Assert-MsBuildAvailable { + <# + .SYNOPSIS Verifies msbuild.exe is on PATH. Exits with error if not found. + #> + $savedPref = $ErrorActionPreference + $ErrorActionPreference = 'Stop' + try { + Get-Command 'msbuild' | Out-Null + } + catch { + Write-Error "msbuild cannot be called from current environment. Ensure it is on PATH (run from VS Developer Command Prompt or EWDK)." + exit 1 + } + finally { + $ErrorActionPreference = $savedPref + } +} + +function Resolve-BuildEnvironment { + <# + .SYNOPSIS + Detects the active build environment, opens a VS Developer Shell when needed, + and returns metadata about the environment. + .DESCRIPTION + Handles the full setup sequence in one place: + 1. Detect mode: EWDK → NuGet → WDK (Auto), or use the explicitly supplied RunMode. + 2. For NuGet / WDK: open a VS Developer Shell if one is not already active, + prompting the user to choose if multiple VS installations with the required + WDK media are found. If the shell is already active, the matching installation + is located via $env:VSINSTALLDIR. + 3. For EWDK: skip VS detection entirely ($env:BuildLab is the authoritative signal). + Returns a hashtable: Name, BuildNumber (int), NuGetVersion, WdkVsComponentVersion. + #> + param( + [string]$RepoRoot, + [string]$RunMode = 'Auto' + ) + + $result = @{ + Name = '' + BuildNumber = [int]0 + NuGetVersion = '' + WdkVsComponentVersion = '' + } + + # ------------------------------------------------------------------------- + # Step 1 – Detect / validate build mode + # ------------------------------------------------------------------------- + + # EWDK: checked first. $env:BuildLab is an active, explicit signal that + # disappears when you close the EWDK prompt, unlike the packages\ folder. + if ($RunMode -eq 'EWDK' -or + ($RunMode -eq 'Auto' -and $env:BuildLab -match '^(?<branch>[^.]+)\.(?<build>\d+)\.(?<qfe>[^.]+)$')) { + + if ($RunMode -eq 'EWDK' -and + $env:BuildLab -notmatch '^(?<branch>[^.]+)\.(?<build>\d+)\.(?<qfe>[^.]+)$') { + Write-Error "RunMode is 'EWDK' but the EWDK environment variable BuildLab is not set. Ensure the EWDK is mounted and the environment is initialised." + exit 1 + } + # Re-run the match to populate $Matches (the Auto branch already matched above; + # the forced-EWDK branch needs an explicit match after the validation guard). + $null = $env:BuildLab -match '^(?<branch>[^.]+)\.(?<build>\d+)\.(?<qfe>[^.]+)$' + $result.Name = "EWDK.$($Matches.branch).$($Matches.build).$($Matches.qfe)" + $result.BuildNumber = [int]$Matches.build + $result.WdkVsComponentVersion = '(not available for EWDK builds)' + return $result + } + + $isNuGet = ($RunMode -eq 'NuGet') -or + ($RunMode -eq 'Auto' -and (Test-Path "$RepoRoot\packages\*")) + + if ($RunMode -eq 'NuGet' -and -not (Test-Path "$RepoRoot\packages\*")) { + Write-Error "RunMode is 'NuGet' but no packages were found under '$RepoRoot\packages\'. Ensure NuGet restore has been run." + exit 1 + } + + # If not EWDK and not NuGet, assume WDK. VS Dev Shell setup below will validate + # the environment; if no VS with WDK media is found, Select-VsInstallation errors out. + + # ------------------------------------------------------------------------- + # Step 2 – Set up VS Developer Shell + # ------------------------------------------------------------------------- + + $vsInstall = $null + + if (-not $env:VSCMD_VER) { + # Dev Shell not active – open one now. + $vsInstall = Select-VsInstallation (Get-VsInstallationsWithWdk) + $devShellDll = Join-Path $vsInstall.InstallationPath 'Common7\Tools\Microsoft.VisualStudio.DevShell.dll' + if (-not (Test-Path $devShellDll)) { + Write-Error "Visual Studio Developer Shell module not found at '$devShellDll'." + exit 1 + } + Import-Module $devShellDll + Enter-VsDevShell -VsInstallPath $vsInstall.InstallationPath + Set-Location $RepoRoot + } + else { + Write-Verbose "VS Developer Shell already active (VSCMD_VER=$env:VSCMD_VER)." + # Locate the matching installation via VSINSTALLDIR so we can read its + # WdkVsComponentVersion without prompting the user again. + # Normalize trailing backslash: VSINSTALLDIR ends with '\', vswhere paths do not. + $normalizedVsInstallDir = $env:VSINSTALLDIR.TrimEnd('\') + $vsInstall = Get-VsInstallationsWithWdk | + Where-Object { $_.InstallationPath.TrimEnd('\') -eq $normalizedVsInstallDir } | + Select-Object -First 1 + if (-not $vsInstall) { + Write-Error "The active Visual Studio Developer Shell ('$env:VSINSTALLDIR') does not have the required WDK media installed. Ensure the WDK Visual Studio component is installed." + exit 1 + } + } + + # ------------------------------------------------------------------------- + # Step 3 – Fill mode-specific fields (Dev Shell is now guaranteed active) + # ------------------------------------------------------------------------- + + if ($isNuGet) { + $result.Name = 'NuGet' + $wdkPackage = Get-ChildItem "$RepoRoot\packages\*WDK.x64*" -Name -ErrorAction SilentlyContinue + $result.NuGetVersion = ([regex]'(?<=x64\.)(\d+\.){3}\d+').Match($wdkPackage).Value + $result.BuildNumber = [int]($result.NuGetVersion.Split('.')[2]) + } + else { + # WDK – Dev Shell is now active, UCRTVersion must be set. + if ($env:UCRTVersion -notmatch '10\.0\.(?<build>\d+)\.0') { + Write-Error "UCRTVersion ('$env:UCRTVersion') is not set or does not match the expected format. Ensure the VS Developer Shell is active." + exit 1 + } + $result.Name = 'WDK' + $result.BuildNumber = [int]$Matches.build + } + + if (-not $vsInstall.WdkVsComponentVersion) { + Write-Error "Could not determine WDK component version for '$($vsInstall.DisplayName)'. Ensure the WDK Visual Studio component is installed." + exit 1 + } + $result.WdkVsComponentVersion = $vsInstall.WdkVsComponentVersion + + return $result +} diff --git a/Building-Locally.md b/Building-Locally.md index 312c5967..ebddbfba 100644 --- a/Building-Locally.md +++ b/Building-Locally.md @@ -1,237 +1,221 @@ -# How to build locally +# Building Driver Samples Locally -## Step 1: Install Tools +## Prerequisites + +### Required tools + +Install PowerShell and Git if you don't have them already: ```powershell winget install --id Microsoft.Powershell --source winget winget install --id Git.Git --source winget ``` -For using WDK NuGet feed based build additionally: +### Install a supported version of the WDK + +See [Download the Windows Driver Kit (WDK)](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) for all available installation options (NuGet packages, MSI installer, EWDK ISO). + +### Clone the repository ```powershell -winget install --id Microsoft.NuGet --source winget +git clone --recurse-submodules "https://github.com/microsoft/Windows-driver-samples.git" +cd ".\Windows-driver-samples" ``` ---- - -## Step 2: Optional: Disable Strong Name Validation +### Environment specific requisites -When: This step is only required if you will be using pre-release versions of the WDK. +- If you are using the WDK via **NuGet**: install NuGet and restore the packages: -As per https://learn.microsoft.com/en-us/windows-hardware/drivers/installing-preview-versions-wdk : +```powershell +winget install --id Microsoft.NuGet --source winget +nuget restore -PackagesDirectory ".\packages" +``` -Run the following commands from an elevated command prompt to disable strong name validation: +- If you are using the WDK via **EWDK**: mount the EWDK ISO, open a terminal in the mounted drive, and launch the build environment: +```powershell +.\LaunchBuildEnv ``` -reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\*,31bf3856ad364e35 /v TestPublicKey /t REG_SZ /d 00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0 /f -reg add HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,31bf3856ad364e35 /v TestPublicKey /t REG_SZ /d 00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0 /f -``` --- -## Step 3: Optional: Install Microsoft .NET Framework 4.7.2 Targeting Pack and Microsoft .NET Framework 4.8.1 SDK +## Building the Samples -When: This step is only required to build sample usb\usbview . +The `Build-Samples.ps1` script auto-detects which WDK environment is active and will build all the samples with all the configurations by default. Just run the following command from **PowerShell**: -### Option A: Install VS Components +```powershell +.\Build-Samples.ps1 +``` -Easy: If you will install Visual Studio (see later) you may at that point select to add both of following individual components: -* .NET Framework 4.7.2 targeting pack -* .NET Framework 4.8.1 SDK +--- -### Option B: Use EWDK +## Expected Output -Easy: If you use EWDK, then all necessary prequisites are included. +``` +--- WDK Sample Build Plan ------------------------------------------ + Environment: NuGet + Build Number: 26100 + NuGet Version: 10.0.26100.1 + WDK VS Component: 10.0.26100.1882 + InfVerif Options: /samples -### Option C: Install Developer Pack + Samples: 132 (0 skipped) + Configurations: Debug, Release + Platforms: x64, arm64 + Combinations: 528 + Exclusions: 4 -Hardest: Install from https://aka.ms/msbuild/developerpacks -> '.NET Framework' -> 'Supported versions' both of following packages: -* .NET Framework 4.7.2 -> Developer Pack -* .NET Framework 4.8.1 -> Developer Pack + Parallelism: 60 jobs (12 cores x 5) + Disk Free (GB): ... + Wipe Outputs: False +-------------------------------------------------------------------- -This will install following Apps: -* Microsoft .NET Framework 4.7.2 SDK -* Microsoft .NET Framework 4.7.2 Targeting Pack -* Microsoft .NET Framework 4.7.2 Targeting Pack (ENU) -* Microsoft .NET Framework 4.8.1 SDK -* Microsoft .NET Framework 4.8.1 Targeting Pack -* Microsoft .NET Framework 4.8.1 Targeting Pack (ENU) +Progress legend: + T=Total B=Built R=Running P=Pending + S=Succeeded E=Excluded U=Unsupported F=Failed O=Sporadic ---- +Building all combinations... -## Step 4: Clone Windows Driver Samples and checkout relevant branch +--- Build Complete ------------------------------------------------- + Elapsed: 12m 42s + Disk Free (GB): ... -```powershell -cd "path\to\your\repos" -git clone --recurse-submodules "https://github.com/microsoft/Windows-driver-samples.git" -cd ".\Windows-driver-samples" -``` + Samples: 132 + Configurations: Debug, Release + Platforms: x64, arm64 + Combinations: 528 -If you are planning to use in-market WDK, then you would typically want to use the 'main' branch: + Succeeded: 526 + Excluded: 0 + Unsupported: 2 + Failed: 0 + Sporadic: 0 -``` -git checkout main + Log directory: .\_logs + CSV report: .\_logs\_overview.csv + HTML report: .\_logs\_overview.htm +-------------------------------------------------------------------- ``` -If you are planning to use a WDK Preview or WDK EEAP release, then you would typically want to use the 'develop' branch: +--- -``` -git checkout develop -``` +## Ways to Run ---- +```powershell +# Show full parameter reference: +Get-Help .\Build-Samples.ps1 -Detailed -## Step 5: Create a "driver build environment" +# Build everything (all samples, configurations, platforms): +.\Build-Samples.ps1 -To build the Windows Driver Samples you need a "driver build environment". In essence an environment that consist of following prerequisites: -* Visual Studio Build Tools including tools such as for example cl.exe and link.exe . -* The Windows Software Development Kit. -* The Windows Driver Kit. +# Verbose output — prints start/finish of each sample: +.\Build-Samples.ps1 -Verbose -### Option A: Use WDK NuGet Packages +# Limit parallelism (useful for debugging build failures): +.\Build-Samples.ps1 -ThrottleLimit 1 -* See [Download the Windows Driver Kit (WDK)](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) for instructions on how to install Visual Studio, but only complete `Step 1`. You do not need to install the SDK or the WDK. -* Launch a "Developer Command Prompt for VS 2022". -* Restore WDK packages from feed : +# Build only samples inside the 'tools' folder: +.\Build-Samples.ps1 -Samples 'tools.*' -```powershell -cd "path\to\your\repos\Windows-driver-samples" -nuget restore -PackagesDirectory ".\packages" +# Build a specific sample for Debug|x64 only: +.\Build-Samples.ps1 -Samples 'tools.sdv.samples.sampledriver' -Configurations 'Debug' -Platforms 'x64' + +# Build every sample linking against an older WDK library set (default is the latest): +.\Build-Samples.ps1 -NtTargetVersion 10.0.22000 ``` -* When this is done you should have a .\packages folder that looks like example below: +`-NtTargetVersion` selects the WDK **`_NT_TARGET_VERSION`** — the OS version of the libraries +the driver links against. It accepts the Windows build number (`10.0.<build>`) or the short +`<build>` tag (e.g. `10.0.22000` or `22000`); when omitted it uses the latest. The valid +values are **auto-discovered from the active WDK** — `Get-NtTargetVersions.ps1` parses the +WDK's `DriverGeneral.xml` rule — so a new WDK version is picked up automatically with no edits. +List what's available with: ```powershell -cd "path\to\your\repos\Windows-driver-samples" -dir /b packages -Microsoft.Windows.SDK.CPP.10.0.26000.1 -Microsoft.Windows.SDK.CPP.x64.10.0.26000.1 -Microsoft.Windows.SDK.CPP.arm64.10.0.26000.1 -Microsoft.Windows.WDK.x64.10.0.26000.1 -Microsoft.Windows.WDK.arm64.10.0.26000.1 +.\Get-NtTargetVersions.ps1 ``` -### Option B: Use the Windows Driver Kit - -* Here you will install each of above prerequisites one at a time. -* See [Download the Windows Driver Kit (WDK)](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) for instructions on how to install Visual Studio, SDK, and WDK. -* Launch a "Developer Command Prompt for VS 2022". - -### Option C: Use an Enterprise WDK - -* You can also simply use the Enterprise WDK (EWDK), a standalone, self-contained command-line environment for building drivers that contains all prerequisites in one combined ISO. -* See [Download the Windows Driver Kit (WDK)](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) for instructions on how to download the EWDK. -* Mount ISO image -* Open a terminal -* `.\LaunchBuildEnv` - --- -## Step 6: Check all samples builds with expected results for all flavors +## Excluding samples from the build + +Samples that are known not to build for a given environment are listed in `exclusions.csv` +at the repo root. Each row excludes a path (with wildcards) for specific +configuration/platform combinations, an optional WDK build-number range, and an optional +`_NT_TARGET_VERSION` range: -```powershell -pwsh -.\Build-AllSamples ``` -Above builds all samples for all configurations and platforms. +Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason +``` -You can refine what exact samples to build, what configurations, and platforms to build. build Here are a few examples: +| Column | Meaning | +| ---------------- | ---------------------------------------------------------------------------------------- | +| `Path` | Sample path (backslashes); supports `*`/`?` wildcards. | +| `Configurations` | `;`-separated `Config\|Platform` patterns, or `*` for all (e.g. `*\|ARM64`, `Debug\|x64`). | +| `MinBuild`/`MaxBuild` | Inclusive WDK build-number range; blank = unbounded. | +| `MinNtTargetVersion`/`MaxNtTargetVersion` | Inclusive `-NtTargetVersion` build-number range (e.g. `22621` matches `10.0.22621`); blank = unbounded. Use this for samples that fail only when linking against older libraries. | +| `Reason` | Human-readable explanation (keep this column last; quote it if it contains commas). | -```powershell -# Get Help: -Get-Help .\Build-AllSamples +A row is applied only when every populated condition matches the current run (path, +configuration/platform, WDK build-number range, and NT target-version range are AND-ed +together). Leave a column blank to ignore that dimension (the default for most rows). -# Build all solutions for all flavors with builds running in parallel: -.\Build-AllSamples +For example, to exclude a sample (Debug builds only) when linking against the `10.0.22621` +library set or older, because it uses a newer API: -# Build with Verbose output (print start and finish of each sample): -.\Build-AllSamples -Verbose +``` +somepath,Debug|*,,,,22621,uses an API newer than the 10.0.22621 library +``` -# Build without massive parallism (slow, but good debugging): -.\Build-AllSamples -ThrottleLimit 1 +--- -# Build the solutions in the tools folder for all flavors: -.\Build-AllSamples -Samples '^tools.' -Configurations 'Debug','Release' -Platforms 'x64','arm64' +## Additional Notes -# Build the solutions in the tools folder for only 'Debug|x64': -.\Build-AllSamples -Samples '^tools.' -Configurations 'Debug' -Platforms 'x64' -``` +### Pre-release WDK: disable strong name validation -Example of expected output: +Required only when using pre-release WDK versions. Run from an elevated command prompt: ``` -Build Environment: NuGet -Build Number: 26100 -Samples: 132 -Configurations: 2 (Debug Release) -Platforms: 2 (x64 arm64) -InfVerif_AdditionalOptions: /samples -Combinations: 528 -LogicalProcessors: 12 -ThrottleFactor: 5 -ThrottleLimit: 60 -WDS_WipeOutputs: -Disk Remaining (GB): ... - -T: Combinations -B: Built -R: Build is running currently -P: Build is pending an available build slot +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\*,31bf3856ad364e35 /v TestPublicKey /t REG_SZ /d 00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0 /f -S: Built and result was 'Succeeded' -E: Built and result was 'Excluded' -U: Built and result was 'Unsupported' (Platform and Configuration combination) -F: Built and result was 'Failed' -O: Built and result was 'Sporadic' +reg add HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,31bf3856ad364e35 /v TestPublicKey /t REG_SZ /d 00240000048000009400000006020000002400005253413100040000010001003f8c902c8fe7ac83af7401b14c1bd103973b26dfafb2b77eda478a2539b979b56ce47f36336741b4ec52bbc51fecd51ba23810cec47070f3e29a2261a2d1d08e4b2b4b457beaa91460055f78cc89f21cd028377af0cc5e6c04699b6856a1e49d5fad3ef16d3c3d6010f40df0a7d6cc2ee11744b5cfb42e0f19a52b8a29dc31b0 /f +``` -Building all combinations... +See [Installing preview versions of the WDK](https://learn.microsoft.com/en-us/windows-hardware/drivers/installing-preview-versions-wdk) for more details. -Built all combinations. +### Building `usb\usbview`: .NET Framework targeting packs -Elapsed time: 12 minutes, 42 seconds. -Disk Remaining (GB): ... -Samples: 132 -Configurations: 2 (Debug Release) -Platforms: 2 (x64 arm64) -Combinations: 528 -Succeeded: 526 -Excluded: 0 -Unsupported: 2 -Failed: 0 -Sporadic: 0 -Log files directory: .\_logs -Overview report: .\_overview.htm -``` +The `usb\usbview` sample requires .NET Framework 4.7.2 and 4.8.1. Choose one option: ---- +- **VS installer** — add the *.NET Framework 4.7.2 targeting pack* and *.NET Framework 4.8.1 SDK* individual components when installing Visual Studio. +- **EWDK** — all required prerequisites are already included. +- **Manual** — download both Developer Packs from https://aka.ms/msbuild/developerpacks. -## 7: NuGet - Additional Notes +### NuGet: restoring a specific WDK version -To restore a specific version of our WDK NuGet packages: +To pin a specific WDK NuGet version before running `nuget restore`: -Follow these steps before running "nuget restore" command: -* Open the .\packages.config file and update the full version (including the branch if required) in all three entries. -* Open the .\Directory.build.props file and update the version and build of the package with the same values as in previous step. -* Open .\Build-SampleSet and change the NuGet build number (used by .\exclusions.csv and for determining infverif flags) -* Now you can run "nuget restore" +1. Open `.\packages.config` and update the version in all entries. +2. Open `.\Directory.build.props` and set the same version. +3. Run `nuget restore -PackagesDirectory ".\packages"`. -A few examples of how to interact with nuget: +Useful NuGet commands: ```powershell -# To add an alternative online NuGet source: -nuget sources add -Name "MyNuGetFeed" -Source "https://nugetserver.com/_packaging/feedname/nuget/v3/index.json" +# Add an online feed: +nuget sources add -Name "MyFeed" -Source "https://nugetserver.com/_packaging/feedname/nuget/v3/index.json" -# To add an alternative local NuGet source: -nuget sources add -Name "MyNuGetFeed" -Source "\\path\to\mylocalrepo" +# Add a local feed: +nuget sources add -Name "MyFeed" -Source "\\path\to\mylocalrepo" -# To remove an alternative NuGet source: -nuget sources remove -Name "MyNuGetFeed" +# Remove a feed: +nuget sources remove -Name "MyFeed" -# To enumerate NuGet locals: +# List local caches: nuget locals all -list -# To clear NuGet locals: +# Clear local caches: nuget locals all -clear ``` + diff --git a/Directory.Build.props b/Directory.Build.props index e5137bea..11951aed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ <Project> -<Import Project="packages\Microsoft.Windows.WDK.x64.10.0.26100.6584\build\native\Microsoft.Windows.WDK.x64.props" Condition="Exists('packages\Microsoft.Windows.WDK.x64.10.0.26100.6584\build\native\Microsoft.Windows.WDK.x64.props') and '$(Platform)' == 'x64'"/> -<Import Project="packages\Microsoft.Windows.WDK.arm64.10.0.26100.6584\build\native\Microsoft.Windows.WDK.arm64.props" Condition="Exists('packages\Microsoft.Windows.WDK.arm64.10.0.26100.6584\build\native\Microsoft.Windows.WDK.arm64.props') and '$(Platform)' == 'ARM64'"/> -<Import Project="packages\Microsoft.Windows.SDK.CPP.x64.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.x64.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.x64.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.x64.props') and '$(Platform)' == 'x64'"/> -<Import Project="packages\Microsoft.Windows.SDK.CPP.arm64.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.arm64.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.arm64.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.arm64.props') and '$(Platform)' == 'ARM64'"/> -<Import Project="packages\Microsoft.Windows.SDK.CPP.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.10.0.26100.6584\build\native\Microsoft.Windows.SDK.cpp.props')"/> +<Import Project="packages\Microsoft.Windows.WDK.x64.10.0.28000.1839\build\native\Microsoft.Windows.WDK.x64.props" Condition="Exists('packages\Microsoft.Windows.WDK.x64.10.0.28000.1839\build\native\Microsoft.Windows.WDK.x64.props') and '$(Platform)' == 'x64'"/> +<Import Project="packages\Microsoft.Windows.WDK.arm64.10.0.28000.1839\build\native\Microsoft.Windows.WDK.arm64.props" Condition="Exists('packages\Microsoft.Windows.WDK.arm64.10.0.28000.1839\build\native\Microsoft.Windows.WDK.arm64.props') and '$(Platform)' == 'ARM64'"/> +<Import Project="packages\Microsoft.Windows.SDK.CPP.x64.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.x64.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.x64.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.x64.props') and '$(Platform)' == 'x64'"/> +<Import Project="packages\Microsoft.Windows.SDK.CPP.arm64.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.arm64.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.arm64.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.arm64.props') and '$(Platform)' == 'ARM64'"/> +<Import Project="packages\Microsoft.Windows.SDK.CPP.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.props" Condition="Exists('packages\Microsoft.Windows.SDK.CPP.10.0.28000.1839\build\native\Microsoft.Windows.SDK.cpp.props')"/> </Project> diff --git a/Get-NtTargetVersions.ps1 b/Get-NtTargetVersions.ps1 new file mode 100644 index 00000000..68088277 --- /dev/null +++ b/Get-NtTargetVersions.ps1 @@ -0,0 +1,100 @@ +<# +.SYNOPSIS + Auto-discovers the valid _NT_TARGET_VERSION values from the active WDK. + +.DESCRIPTION + The _NT_TARGET_VERSION property (the OS version of the libraries a driver links against) + is an enumeration defined by the WDK in its 'DriverGeneral.xml' rule file. This script + locates that rule file (from the restored NuGet packages, or the installed WDK) and parses + the enumeration so that nothing in the build needs a hard-coded version list: when a new + WDK adds a new _NT_TARGET_VERSION it is picked up automatically. + + Returns one object per Windows 10/11 entry, newest-first: + Version e.g. 10.0.28000 (use with -NtTargetVersion) + Tag e.g. 28000 (short, filename/CI-friendly) + Code e.g. 0xA000012 (the NTDDI value passed to msbuild) + Build e.g. 28000 (numeric, for sorting/ranges) + +.PARAMETER XmlPath + Optional explicit path to a DriverGeneral.xml. When omitted the newest available rule file + is auto-located. + +.PARAMETER Newest + Return only the newest N versions (0 = all). Useful for bounding the CI build matrix. + +.PARAMETER AsMatrixJson + Emit a compact JSON array of { version, tag } objects for a GitHub Actions matrix + (consumed via fromJSON). Implies a single-line output. + +.EXAMPLE + .\Get-NtTargetVersions.ps1 # all discovered versions (objects) + +.EXAMPLE + .\Get-NtTargetVersions.ps1 -Newest 4 -AsMatrixJson +#> +[CmdletBinding()] +param( + [string]$XmlPath, + [int]$Newest = 0, + [switch]$AsMatrixJson +) + +function Find-DriverGeneralXml { + # Prefer the restored NuGet WDK package (matches what the build actually uses), then the + # installed WDK. Within each source, pick the highest build version. + $candidates = @() + $candidates += Get-ChildItem -Path (Join-Path $PSScriptRoot 'packages') -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + foreach ($kitsRoot in @("${env:ProgramFiles(x86)}\Windows Kits\10\build", "${env:ProgramFiles}\Windows Kits\10\build")) { + if ($kitsRoot -and (Test-Path $kitsRoot)) { + $candidates += Get-ChildItem -Path $kitsRoot -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + } + } + # EWDK / arbitrary build environments expose the build tree via these variables. + foreach ($envRoot in @($env:WDKContentRoot, $env:WindowsSdkDir)) { + if ($envRoot -and (Test-Path $envRoot)) { + $buildDir = Join-Path $envRoot 'build' + if (Test-Path $buildDir) { + $candidates += Get-ChildItem -Path $buildDir -Recurse -Filter 'DriverGeneral.xml' -ErrorAction SilentlyContinue + } + } + } + if (-not $candidates) { return $null } + # Order by the build version embedded in the path (e.g. ...\10.0.28000.0\...), highest first. + return ($candidates | Sort-Object { + if ($_.FullName -match '10\.0\.(\d+)\.\d') { [int]$Matches[1] } else { 0 } + } -Descending | Select-Object -First 1).FullName +} + +if (-not $XmlPath) { $XmlPath = Find-DriverGeneralXml } +if (-not $XmlPath -or -not (Test-Path $XmlPath)) { + throw "Could not locate DriverGeneral.xml. Restore the WDK NuGet packages or install the WDK, or pass -XmlPath." +} + +[xml]$xml = Get-Content -Path $XmlPath -Raw +$enum = $xml.ProjectSchemaDefinitions.Rule.EnumProperty | Where-Object { $_.Name -eq '_NT_TARGET_VERSION' } +if (-not $enum) { throw "No _NT_TARGET_VERSION enumeration found in '$XmlPath'." } + +$versions = + $enum.EnumValue | + ForEach-Object { + # DisplayName is e.g. "Windows 10.0.28000"; Name is the NTDDI code e.g. "0xA000012". + if ("$($_.DisplayName)" -match 'Windows\s+(?<v>10\.0\.(?<b>\d+))\s*$') { + [pscustomobject]@{ + Version = $Matches.v + Tag = $Matches.b + Code = $_.Name + Build = [int]$Matches.b + } + } + } | + Sort-Object Build -Descending + +if ($Newest -gt 0) { $versions = $versions | Select-Object -First $Newest } + +if ($AsMatrixJson) { + # Compact, single-line JSON for a GitHub Actions matrix: [{ "version": "...", "tag": "..." }, ...] + $matrix = @($versions | ForEach-Object { [ordered]@{ version = $_.Version; tag = $_.Tag } }) + return ($matrix | ConvertTo-Json -Compress -Depth 3) +} + +return $versions diff --git a/ListAllSamples.ps1 b/ListAllSamples.ps1 new file mode 100644 index 00000000..1a1a4a78 --- /dev/null +++ b/ListAllSamples.ps1 @@ -0,0 +1,49 @@ +<# +.SYNOPSIS + Enumerates all available sample solutions in the repository and writes them to the console. + +.DESCRIPTION + Searches for all .sln files recursively from the repo root, excludes NuGet package directories + (paths containing 'packages' as a segment), computes a normalized sample name for each, and writes + the sorted list to stdout (one sample name per line). + + The sample name is derived from the relative directory path: backslashes are replaced with dots + and the result is lowercased. + +.EXAMPLE + .\ListAllSamples + + Discovers all samples and writes the sorted names to the console. + +.OUTPUTS + Sorted sample names written to stdout, one per line. +#> + +[CmdletBinding()] +param() + +$root = (Get-Location).Path + +# Discover all .sln files +$solutionFiles = Get-ChildItem -Path $root -Recurse -Filter *.sln | Select-Object -ExpandProperty FullName + +$sampleNames = @{} + +foreach ($file in $solutionFiles) { + $dir = (Get-Item $file).DirectoryName + $dirNorm = $dir.Replace($root, '').Trim('\').Replace('\', '.').ToLower() + + if ($dirNorm -match '(^|\.|\b)packages(\.|$)') { + Write-Verbose "Ignored NuGet package directory: $dirNorm" + continue + } + + if (-not $sampleNames.ContainsKey($dirNorm)) { + $sampleNames[$dirNorm] = $true + } +} + +$sortedNames = $sampleNames.Keys | Sort-Object + +Write-Verbose "Found $($sortedNames.Count) samples." +$sortedNames | Write-Output diff --git a/_wdk_utils/winget/configs/wdk-desktop.vsconfig b/_wdk_utils/winget/configs/wdk-desktop.vsconfig new file mode 100644 index 00000000..92b73d04 --- /dev/null +++ b/_wdk_utils/winget/configs/wdk-desktop.vsconfig @@ -0,0 +1,27 @@ +{ + "version": "1.0", + "components": [ + "Component.Microsoft.Windows.DriverKit", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Component.DiagnosticTools", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.ATL.Spectre", + "Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre", + "Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre", + "Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Workload.NativeDesktop" + ], + "extensions": [] +}
\ No newline at end of file diff --git a/configuration.dsc.yaml b/_wdk_utils/winget/configs/wdk-vscommunity.dsc.yaml index 3d25ff06..5d8c32f2 100644 --- a/configuration.dsc.yaml +++ b/_wdk_utils/winget/configs/wdk-vscommunity.dsc.yaml @@ -4,10 +4,10 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: - description: Install Visual Studio 2022 Community + description: Install Visual Studio Community allowPrerelease: true settings: - id: Microsoft.VisualStudio.2022.Community + id: Microsoft.VisualStudio.Community source: winget useLatest: true - resource: Microsoft.VisualStudio.DSC/VSComponents @@ -18,38 +18,37 @@ properties: description: Install required VS workloads and components settings: productId: Microsoft.VisualStudio.Product.Community - channelId: VisualStudio.17.Release + channelId: VisualStudio.18.Release includeRecommended: false components: - - Microsoft.VisualStudio.Component.VC.CoreBuildTools - - Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core - - Microsoft.VisualStudio.Component.VC.Tools.x86.x64 - - Microsoft.VisualStudio.Component.VC.Tools.ARM64 - - Microsoft.VisualStudio.Component.VC.Tools.ARM64EC - - Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre - - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre - - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre - - Microsoft.VisualStudio.Component.VC.Redist.14.Latest - - Microsoft.VisualStudio.Component.Windows10SDK - - Microsoft.VisualStudio.Component.VC.ATL - - Microsoft.VisualStudio.Component.VC.ATL.ARM64 - - Microsoft.VisualStudio.Component.VC.ATL.Spectre + - Component.Microsoft.Windows.DriverKit + - Microsoft.Component.MSBuild + - Microsoft.VisualStudio.Component.CoreEditor + - Microsoft.VisualStudio.Component.DiagnosticTools + - Microsoft.VisualStudio.Component.Roslyn.Compiler + - Microsoft.VisualStudio.Component.TextTemplating - Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre - - Microsoft.VisualStudio.Component.VC.ATLMFC + - Microsoft.VisualStudio.Component.VC.ATL.Spectre - Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre - - Microsoft.VisualStudio.Component.VC.ASAN - - Microsoft.VisualStudio.Component.NuGet.BuildTools - - Microsoft.VisualStudio.Component.VC.MFC.ARM64 + - Microsoft.VisualStudio.Component.VC.CoreIde - Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Redist.14.Latest + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre + - Microsoft.VisualStudio.Component.VC.Tools.ARM64 + - Microsoft.VisualStudio.Component.VC.Tools.ARM64EC + - Microsoft.VisualStudio.Component.VC.Tools.x86.x64 + - Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core + - Microsoft.VisualStudio.Workload.CoreEditor - Microsoft.VisualStudio.Workload.NativeDesktop - - Component.Microsoft.Windows.DriverKit - resource: Microsoft.WinGet.DSC/WinGetPackage id: sdkPackage directives: - description: Install Windows SDK version 26100 + description: Install Windows SDK version 28000 allowPrerelease: true settings: - id: Microsoft.WindowsSDK.10.0.26100 + id: Microsoft.WindowsSDK.10.0.28000 source: winget useLatest: true - resource: Microsoft.WinGet.DSC/WinGetPackage @@ -57,10 +56,10 @@ properties: dependsOn: - sdkPackage directives: - description: Install Windows Driver Kit version 26100 + description: Install Windows Driver Kit version 28000 allowPrerelease: true settings: - id: Microsoft.WindowsWDK.10.0.26100 + id: Microsoft.WindowsWDK.10.0.28000 source: winget useLatest: true configurationVersion: 0.2.1 diff --git a/configuration_vsonly.dsc.yaml b/_wdk_utils/winget/configs/wdk-vsenterprise.dsc.yaml index 9d86a4f7..a7a59b6f 100644 --- a/configuration_vsonly.dsc.yaml +++ b/_wdk_utils/winget/configs/wdk-vsenterprise.dsc.yaml @@ -4,10 +4,10 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: - description: Install Visual Studio 2022 Community + description: Install Visual Studio Enterprise allowPrerelease: true settings: - id: Microsoft.VisualStudio.2022.Community + id: Microsoft.VisualStudio.Enterprise source: winget useLatest: true - resource: Microsoft.VisualStudio.DSC/VSComponents @@ -17,30 +17,49 @@ properties: directives: description: Install required VS workloads and components settings: - productId: Microsoft.VisualStudio.Product.Community - channelId: VisualStudio.17.Release + productId: Microsoft.VisualStudio.Product.Enterprise + channelId: VisualStudio.18.Release includeRecommended: false components: - - Microsoft.VisualStudio.Component.VC.CoreBuildTools - - Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core - - Microsoft.VisualStudio.Component.VC.Tools.x86.x64 - - Microsoft.VisualStudio.Component.VC.Tools.ARM64 - - Microsoft.VisualStudio.Component.VC.Tools.ARM64EC - - Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre - - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre - - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre - - Microsoft.VisualStudio.Component.VC.Redist.14.Latest - - Microsoft.VisualStudio.Component.Windows10SDK - - Microsoft.VisualStudio.Component.VC.ATL - - Microsoft.VisualStudio.Component.VC.ATL.ARM64 - - Microsoft.VisualStudio.Component.VC.ATL.Spectre + - Component.Microsoft.Windows.DriverKit + - Microsoft.Component.MSBuild + - Microsoft.VisualStudio.Component.CoreEditor + - Microsoft.VisualStudio.Component.DiagnosticTools + - Microsoft.VisualStudio.Component.Roslyn.Compiler + - Microsoft.VisualStudio.Component.TextTemplating - Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre - - Microsoft.VisualStudio.Component.VC.ATLMFC + - Microsoft.VisualStudio.Component.VC.ATL.Spectre - Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre - - Microsoft.VisualStudio.Component.VC.ASAN - - Microsoft.VisualStudio.Component.NuGet.BuildTools - - Microsoft.VisualStudio.Component.VC.MFC.ARM64 + - Microsoft.VisualStudio.Component.VC.CoreIde - Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Redist.14.Latest + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre + - Microsoft.VisualStudio.Component.VC.Tools.ARM64 + - Microsoft.VisualStudio.Component.VC.Tools.ARM64EC + - Microsoft.VisualStudio.Component.VC.Tools.x86.x64 + - Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core + - Microsoft.VisualStudio.Workload.CoreEditor - Microsoft.VisualStudio.Workload.NativeDesktop - - Component.Microsoft.Windows.DriverKit + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: sdkPackage + directives: + description: Install Windows SDK version 28000 + allowPrerelease: true + settings: + id: Microsoft.WindowsSDK.10.0.28000 + source: winget + useLatest: true + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: wdkPackage + dependsOn: + - sdkPackage + directives: + description: Install Windows Driver Kit version 28000 + allowPrerelease: true + settings: + id: Microsoft.WindowsWDK.10.0.28000 + source: winget + useLatest: true configurationVersion: 0.2.1 diff --git a/_wdk_utils/winget/configs/wdk-vsprofessional.dsc.yaml b/_wdk_utils/winget/configs/wdk-vsprofessional.dsc.yaml new file mode 100644 index 00000000..cdc97e69 --- /dev/null +++ b/_wdk_utils/winget/configs/wdk-vsprofessional.dsc.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2 +properties: + resources: + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: vsPackage + directives: + description: Install Visual Studio Professional + allowPrerelease: true + settings: + id: Microsoft.VisualStudio.Professional + source: winget + useLatest: true + - resource: Microsoft.VisualStudio.DSC/VSComponents + id: vsComponents + dependsOn: + - vsPackage + directives: + description: Install required VS workloads and components + settings: + productId: Microsoft.VisualStudio.Product.Professional + channelId: VisualStudio.18.Release + includeRecommended: false + components: + - Component.Microsoft.Windows.DriverKit + - Microsoft.Component.MSBuild + - Microsoft.VisualStudio.Component.CoreEditor + - Microsoft.VisualStudio.Component.DiagnosticTools + - Microsoft.VisualStudio.Component.Roslyn.Compiler + - Microsoft.VisualStudio.Component.TextTemplating + - Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.ATL.Spectre + - Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre + - Microsoft.VisualStudio.Component.VC.CoreIde + - Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Redist.14.Latest + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.ARM64EC.Spectre + - Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre + - Microsoft.VisualStudio.Component.VC.Tools.ARM64 + - Microsoft.VisualStudio.Component.VC.Tools.ARM64EC + - Microsoft.VisualStudio.Component.VC.Tools.x86.x64 + - Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core + - Microsoft.VisualStudio.Workload.CoreEditor + - Microsoft.VisualStudio.Workload.NativeDesktop + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: sdkPackage + directives: + description: Install Windows SDK version 28000 + allowPrerelease: true + settings: + id: Microsoft.WindowsSDK.10.0.28000 + source: winget + useLatest: true + - resource: Microsoft.WinGet.DSC/WinGetPackage + id: wdkPackage + dependsOn: + - sdkPackage + directives: + description: Install Windows Driver Kit version 28000 + allowPrerelease: true + settings: + id: Microsoft.WindowsWDK.10.0.28000 + source: winget + useLatest: true + configurationVersion: 0.2.1 diff --git a/audio/SoundWire/Documentation/IntroductionToSdca.docx b/audio/SoundWire/Documentation/IntroductionToSdca.docx Binary files differnew file mode 100644 index 00000000..1bf9d7de --- /dev/null +++ b/audio/SoundWire/Documentation/IntroductionToSdca.docx diff --git a/audio/SoundWire/LICENSE b/audio/SoundWire/LICENSE new file mode 100644 index 00000000..6ef3ee38 --- /dev/null +++ b/audio/SoundWire/LICENSE @@ -0,0 +1,23 @@ +The Microsoft Public License (MS-PL) +Copyright (c) 2015 Microsoft + +This license governs use of the accompanying software. If you use the software, you + accept this license. If you do not accept the license, do not use the software. + +1. Definitions + The terms "reproduce," "reproduction," "derivative works," and "distribution" have the + same meaning here as under U.S. copyright law. + A "contribution" is the original software, or any additions or changes to the software. + A "contributor" is any person that distributes its contribution under this license. + "Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. diff --git a/audio/SoundWire/README.md b/audio/SoundWire/README.md new file mode 100644 index 00000000..8ed5ffb3 --- /dev/null +++ b/audio/SoundWire/README.md @@ -0,0 +1,2 @@ +# Soundwire +Microsoft Soundwire Samples and Guides diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/inc/CommonMacros.h b/audio/SoundWire/Samples/SdcaVad/Apo/inc/CommonMacros.h new file mode 100644 index 00000000..097c6d47 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/inc/CommonMacros.h @@ -0,0 +1,337 @@ +//**@@@*@@@**************************************************** +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//**@@@*@@@**************************************************** + +// +// FileName: CommonMacros.h +// +// Abstract: Useful macros +// +// ---------------------------------------------------------------------------- + + +#pragma once +#include <windef.h> +#include <windows.h> + + +//------------------------------------------------------------------------- +// 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 FALSE, 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_FALSE_JUMP(condition, label) \ + if (!condition) \ + { \ + goto label; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// If the hresult passed FAILED, jump to the given label. +// +// Parameters: +// +// _hresult - [in] Value to check +// label - [in] label to jump if condition is met +// +#define IF_FAILED_JUMP(_hresult, label) \ + if (FAILED(_hresult)) \ + { \ + goto label; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// If the hresult passed SUCCEEDED, jump to the given label. +// +// Parameters: +// +// _hresult - [in] Value to check +// label - [in] label to jump if condition is met +// +#define IF_SUCCEEDED_JUMP(_hresult, label) \ + if (SUCCEEDED(_hresult)) \ + { \ + 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 hresult FAILED, perform the given statement then jump to +// the given label. +// +// Parameters: +// +// _hresult - [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(_hresult, action, label) \ + if (FAILED(_hresult)) \ + { \ + action; \ + goto label; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Closes a handle and assigns NULL. +// +// Parameters: +// +// h - [in] handle to close +// +#define SAFE_CLOSE_HANDLE(h) \ + if (NULL != h) \ + { \ + CloseHandle(h); \ + h = NULL; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Addref an interface pointer +// +// Parameters: +// +// p - [in] object to addref +// +#define SAFE_ADDREF(p) \ + if (NULL != p) \ + { \ + (p)->AddRef();; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Releases an interface pointer and assigns NULL. +// +// Parameters: +// +// p - [in] object to release +// +#define SAFE_RELEASE(p) \ + if (NULL != p) \ + { \ + (p)->Release(); \ + (p) = NULL; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Deletes a pointer and assigns NULL. Do not check for NULL because +// the default delete operator checks for it. +// +// Parameters: +// +// p - [in] object to delete +// +#define SAFE_DELETE(p) \ + delete p; \ + p = NULL; + +//------------------------------------------------------------------------- +// Description: +// +// Deletes an array pointer and assigns NULL. Do not check for NULL because +// the default delete operator checks for it. +// +// Parameters: +// +// p - [in] Array to delete +// +#define SAFE_DELETE_ARRAY(p) \ + delete [] p; \ + p = NULL; + +//------------------------------------------------------------------------- +// Description: +// +// Frees a block of memory allocated by CoTaskMemAlloc and assigns NULL to +// the pointer +// +// Parameters: +// +// p - [in] Pointer to memory to free +// +#define SAFE_COTASKMEMFREE(p) \ + if (NULL != p) \ + { \ + CoTaskMemFree(p); \ + (p) = NULL; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Frees a DLL loaded with LoadLibrary and assigns NULL to the handle +// +// Parameters: +// +// h - [in] Handle to DLL to free +// +#define SAFE_FREELIBRARY(h) \ + if (NULL != h) \ + { \ + FreeLibrary(h); \ + (h) = NULL; \ + } + +//------------------------------------------------------------------------- +// Description: +// +// Used to validate a read pointer +// +// Parameters: +// +// p - [in] read pointer. +// s - [in] size of memory in bytes pointed to by p. +// +#define IS_VALID_READ_POINTER(p, s) ((NULL != p) || (0 == s)) + +//------------------------------------------------------------------------- +// Description: +// +// Used to validate a write pointer +// +// Parameters: +// +// p - [in] write pointer. +// s - [in] size of memory in bytes pointed to by p. +// +#define IS_VALID_WRITE_POINTER(p, s) ((NULL != p) || (0 == s)) + +//------------------------------------------------------------------------- +// Description: +// +// Used to validate a read pointer of a particular type +// +// Parameters: +// +// p - [in] typed read pointer +// +#define IS_VALID_TYPED_READ_POINTER(p) IS_VALID_READ_POINTER((p), sizeof *(p)) + +//------------------------------------------------------------------------- +// Description: +// +// Used to validate a write pointer of a particular type +// +// Parameters: +// +// p - [in] typed write pointer +// +#define IS_VALID_TYPED_WRITE_POINTER(p) IS_VALID_WRITE_POINTER((p), sizeof *(p)) + +// --------------------------------------------------------------------------- +// Macros that wrap windows messages. Similar to those in windowsX.h and +// commctrl.h +// +#if !defined Static_SetIcon +#define Static_SetIcon(hwnd, hi) \ + (BOOL)SNDMSG((hwnd), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)(hi)) +#endif + +#define TrackBar_SetTickFrequency(hwnd, f) \ + (BOOL)SNDMSG((hwnd), TBM_SETTICFREQ, (WPARAM)(f), 0) + +#define TrackBar_SetBuddy(hwnd, f, hbud) \ + (HWND)SNDMSG((hwnd), TBM_SETBUDDY, (WPARAM)(f), (LPARAM)hbud) + +#define TrackBar_GetPos(hwnd) \ + (int)SNDMSG((hwnd), TBM_GETPOS, 0, 0) + +#define TrackBar_SetPos(hwnd, pos) \ + SNDMSG((hwnd), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos) + +#define TrackBar_SetRange(hwnd, min, max) \ + SNDMSG((hwnd), TBM_SETRANGE , (WPARAM)TRUE, (LPARAM) MAKELONG(min, max)) + +#define TrackBar_SetThumbLength(hwnd, l) \ + SNDMSG((hwnd), TBM_SETTHUMBLENGTH, (WPARAM)l, 0); + +#define TrackBar_SetPageSize(hwnd, n) \ + SNDMSG((hwnd), TBM_SETPAGESIZE, 0, (LPARAM)n) + +#define Window_GetFont(hwnd) \ + (HFONT)SNDMSG((hwnd), WM_GETFONT, 0, 0) + +#define Window_SetFont(hwnd, font) \ + SNDMSG((hwnd), WM_SETFONT, (WPARAM)font, FALSE) + + +// ---------------------------------------------------------------------- +// A struct for holding a rect in easier terms than a RECT struct +// +struct SRECT +{ + int x, y, w, h; + SRECT() + { + x = y = w = h = 0; + } + SRECT(int X, int Y, int W, int H) + { + x = X; y = Y; w = W; h = H; + } + SRECT(RECT* prc) + { + x = prc->left; + y = prc->top; + w = prc->right - prc->left; + h = prc->bottom - prc->top; + } +}; + +#define HNS_PER_SECOND (10ull * 1000ull * 1000ull) diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/inc/CustomPropKeys.h b/audio/SoundWire/Samples/SdcaVad/Apo/inc/CustomPropKeys.h new file mode 100644 index 00000000..dab286a5 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/inc/CustomPropKeys.h @@ -0,0 +1,39 @@ +// Microsoft Windows +// Copyright (C) Microsoft Corporation. All rights reserved. +// +#pragma once + +// header files for imported files +#include "propidl.h" + +#ifdef DEFINE_PROPERTYKEY +#undef DEFINE_PROPERTYKEY +#endif + +#ifdef INITGUID +#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } +#else +#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY name +#endif // INITGUID + +// ---------------------------------------------------------------------- +// +// PKEY_Endpoint_Enable_Channel_Swap_SFX: When value is 0x00000001, Channel Swap local effect is enabled +// {A44531EF-5377-4944-AE15-53789A9629C7},2 +// vartype = VT_UI4 +DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Channel_Swap_SFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 2); + +// PKEY_Endpoint_Enable_Channel_Swap_MFX: When value is 0x00000001, Channel Swap global effect is enabled +// {A44531EF-5377-4944-AE15-53789A9629C7},3 +// vartype = VT_UI4 +DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Channel_Swap_MFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 3); + +// PKEY_Endpoint_Enable_Delay_SFX: When value is 0x00000001, Delay local effect is enabled +// {A44531EF-5377-4944-AE15-53789A9629C7},4 +// vartype = VT_UI4 +DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Delay_SFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 4); + +// PKEY_Endpoint_Enable_Delay_MFX: When value is 0x00000001, Delay global effect is enabled +// {A44531EF-5377-4944-AE15-53789A9629C7},5 +// vartype = VT_UI4 +DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Delay_MFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 5); diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.cpp b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.cpp new file mode 100644 index 00000000..d67eaca0 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.cpp @@ -0,0 +1,62 @@ +// +// KWSApo.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of ProcessBuffer +// +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "KWSApo.h" + +#pragma AVRT_CODE_BEGIN +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ) +{ + ZeroMemory(pf32Frames, sizeof(FLOAT32) * u32FrameCount * u32SamplesPerFrame); +} +#pragma AVRT_CODE_END + +#pragma AVRT_CODE_BEGIN +void ProcessBuffer( + FLOAT32 *pf32OutputFrames, + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + INTERLEAVED_AUDIO_FORMAT_INFORMATION *formatInfo) +{ + UINT32 totalChannelCount = (formatInfo->PrimaryChannelCount + formatInfo->InterleavedChannelCount); + + ASSERT_REALTIME(); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + ATLASSERT( IS_VALID_TYPED_WRITE_POINTER(pf32OutputFrames) ); + + // loop through samples + while (u32ValidFrameCount--) + { + // copy over the Primary channel data + for (UINT32 i = formatInfo->PrimaryChannelStartPosition; i < (formatInfo->PrimaryChannelStartPosition + formatInfo->PrimaryChannelCount); i++) + { + *pf32OutputFrames = *(pf32InputFrames + i); + pf32OutputFrames++; + } + + // step forward to the next frame, ignoring interleaved data + pf32InputFrames += (totalChannelCount); + } +} + +#pragma AVRT_CODE_END + diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.h b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.h new file mode 100644 index 00000000..066d5c5b --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.h @@ -0,0 +1,134 @@ +// +// KWSApo.h -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Declaration of the CKWSApoEFX class. +// + +#pragma once + +#include <audioenginebaseapo.h> +#include <BaseAudioProcessingObject.h> +#include <KWSApoInterface.h> +#include <KWSApoDll.h> + +#include <commonmacros.h> +#include <devicetopology.h> + +_Analysis_mode_(_Analysis_code_type_user_driver_) + +#pragma AVRT_VTABLES_BEGIN +// KWS APO class - EFX +class CKWSApoEFX : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CKWSApoEFX, &CLSID_KWSApoEFX>, + public CBaseAudioProcessingObject, + public IMMNotificationClient, + public IAudioSystemEffects2, + public IKWSApoEFX +{ +public: + // constructor + CKWSApoEFX() + : CBaseAudioProcessingObject(sm_RegProperties) + { + } + + virtual ~CKWSApoEFX(); // destructor + +DECLARE_REGISTRY_RESOURCEID(IDR_KWSAPOEFX) + +BEGIN_COM_MAP(CKWSApoEFX) + COM_INTERFACE_ENTRY(IKWSApoEFX) + COM_INTERFACE_ENTRY(IAudioSystemEffects) + COM_INTERFACE_ENTRY(IAudioSystemEffects2) + COM_INTERFACE_ENTRY(IMMNotificationClient) + COM_INTERFACE_ENTRY(IAudioProcessingObjectRT) + COM_INTERFACE_ENTRY(IAudioProcessingObject) + COM_INTERFACE_ENTRY(IAudioProcessingObjectConfiguration) +END_COM_MAP() + +DECLARE_PROTECT_FINAL_CONSTRUCT() + +public: + STDMETHOD_(void, APOProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections); + + STDMETHOD(GetLatency)(HNSTIME* pTime); + + STDMETHOD(LockForProcess)(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections); + + STDMETHOD(Initialize)(UINT32 cbDataSize, BYTE* pbyData); + + // IAudioSystemEffects2 + STDMETHOD(GetEffectsList)(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event); + + // IAudioProcessingObject + STDMETHOD(IsInputFormatSupported)(IAudioMediaType *pOutputFormat, IAudioMediaType *pRequestedInputFormat, IAudioMediaType **ppSupportedInputFormat); + STDMETHOD(IsOutputFormatSupported)(IAudioMediaType *pInputFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat); + STDMETHOD(GetInputChannelCount)(UINT32 *pu32ChannelCount); + + // IMMNotificationClient + STDMETHODIMP OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(dwNewState); + return S_OK; + } + STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + return S_OK; + } + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) + { + UNREFERENCED_PARAMETER(flow); + UNREFERENCED_PARAMETER(role); + UNREFERENCED_PARAMETER(pwstrDefaultDeviceId); + return S_OK; + } + STDMETHODIMP OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) + { + UNREFERENCED_PARAMETER(pwstrDeviceId); + UNREFERENCED_PARAMETER(key); + return S_OK; + } + +public: + CComPtr<IPropertyStore> m_spAPOSystemEffectsProperties; + CComPtr<IMMDeviceEnumerator> m_spEnumerator; + static const CRegAPOProperties<1> sm_RegProperties; // registration properties + INTERLEAVED_AUDIO_FORMAT_INFORMATION m_FormatInfo{ 0 }; +}; +#pragma AVRT_VTABLES_END + +OBJECT_ENTRY_AUTO(__uuidof(KWSApoEFX), CKWSApoEFX) + +// +// Declaration of the ProcessBuffer routine. +// +void ProcessBuffer( + FLOAT32 *pf32OutputFrames, + const FLOAT32 *pf32InputFrames, + UINT32 u32ValidFrameCount, + INTERLEAVED_AUDIO_FORMAT_INFORMATION *formatInfo); + +// +// Convenience methods +// + +void WriteSilence( + _Out_writes_(u32FrameCount * u32SamplesPerFrame) + FLOAT32 *pf32Frames, + UINT32 u32FrameCount, + UINT32 u32SamplesPerFrame ); + diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.png b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.png Binary files differnew file mode 100644 index 00000000..3a6e102a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.png diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.vcxproj b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.vcxproj new file mode 100644 index 00000000..10928047 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.vcxproj @@ -0,0 +1,468 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{47358AD6-A48A-465B-965F-0A66F8BDFE23}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{D5CCDCB1-348E-414E-BB0F-33C773760034}</SampleGuid> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <EmbedManifest>false</EmbedManifest> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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> + <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|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <TargetName>SDCAVKwsAPO</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary> + </RuntimeLibrary> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary> + </RuntimeLibrary> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\;.</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <RuntimeLibrary /> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;AudioBaseProcessingObjectV140.lib;audiomediatypecrt.lib;AudioEng.lib</AdditionalDependencies> + <ModuleDefinitionFile>KWSApoDll.def</ModuleDefinitionFile> + <AdditionalOptions>/ignore:4217,4049 %(AdditionalOptions)</AdditionalOptions> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="KWSApo.cpp" /> + <ClCompile Include="KWSApoDll.cpp" /> + <ClCompile Include="KWSApoEFX.cpp" /> + <Midl Include="KWSApoDll.idl" /> + <Midl Include="KWSApoInterface.idl" /> + <ResourceCompile Include="KWSApoDll.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.vcxproj.Filters new file mode 100644 index 00000000..a5710c73 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApo.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>{5f4ff11d-7a0b-4f75-9d79-744ae028cc53}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{bd103b81-05b2-440e-84e7-0723d7fe4109}</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>{a57b6b78-38ae-4348-ade3-0200e81a3dd7}</UniqueIdentifier> + </Filter> + <Filter Include="IDL Files"> + <Extensions>idl</Extensions> + <UniqueIdentifier>{c6318700-1bce-4812-92f1-160881e4c976}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.cpp b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.cpp new file mode 100644 index 00000000..286b7869 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.cpp @@ -0,0 +1,71 @@ +// +// KWSApoDll.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// KWSApoDll.cpp : Implementation of DLL Exports. + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include "resource.h" +#include "KWSApoDll.h" +#include <KWSApo.h> + +#include <KWSApoDll_i.c> + + +//------------------------------------------------------------------------- +// Array of APO_REG_PROPERTIES structures implemented in this module. +// Each new APO implementation will be added to this array. +// +APO_REG_PROPERTIES const *gCoreAPOs[] = +{ + &CKWSApoEFX::sm_RegProperties.m_Properties +}; + +// {secret} +class CKWSApoDllModule : public CAtlDllModuleT< CKWSApoDllModule > +{ +public : + DECLARE_LIBID(LIBID_KWSApoDlllib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_KWSAPODLL, "{0A21D954-674A-4C09-806E-DB4FBE8F199C}") + +}; + +// {secret} +CKWSApoDllModule _AtlModule; + + +// {secret} +extern "C" BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID lpReserved) +{ + if (DLL_PROCESS_ATTACH == dwReason) + { + } + // do necessary cleanup only if the DLL is being unloaded dynamically + else if ((DLL_PROCESS_DETACH == dwReason) && (NULL == lpReserved)) + { + } + + return _AtlModule.DllMain(dwReason, lpReserved); +} + + +// {secret} +STDAPI DllCanUnloadNow(void) +{ + return _AtlModule.DllCanUnloadNow(); +} + + +// {secret} +STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) +{ + return _AtlModule.DllGetClassObject(rclsid, riid, ppv); +} diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.def b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.def new file mode 100644 index 00000000..3f3b0c5a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.def @@ -0,0 +1,4 @@ + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE
\ No newline at end of file diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.idl b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.idl new file mode 100644 index 00000000..086643d7 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.idl @@ -0,0 +1,40 @@ +// +// KWSAPODll.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Author: +// +// Description: +// +// KWSAPODll.idl : Definition of COM interfaces and coclasses for the DLL. + +import "oaidl.idl"; +import "ocidl.idl"; +import "KWSApoInterface.idl"; + +//------------------------------------------------------------------------- +// KWSApoDlllib +// +[ + uuid(E928E566-CBA7-4181-9B8B-8822E2BD28AB), + version(1.0) +] +library KWSApoDlllib +{ + importlib("stdole2.tlb"); + + // for KWS APO - EFX + [ + uuid(9D89F614-F9D6-40DD-9F21-5E69FA3981ED) + ] + coclass KWSApoEFX + { + interface IAudioProcessingObject; + interface IAudioProcessingObjectRT; + interface IAudioProcessingObjectConfiguration; + interface IMMNotificationClient; + interface IAudioSystemEffects; + [default] interface IKWSApoEFX; + }; + + +} diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rc b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rc new file mode 100644 index 00000000..9add8452 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rc @@ -0,0 +1,20 @@ +#if 0 +Copyright (c) Microsoft Corporation. All Rights Reserved +#endif + +#include "resource.h" +#include "winres.h" +#include <ntverp.h> +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "KWS APO" +#define VER_INTERNALNAME_STR "KWSApo" +#define VER_ORIGINALFILENAME_STR "KWSApo.Dll" +#include <Common.ver> + +IDR_KWSAPODLL REGISTRY "KWSApoDll.rgs" +IDR_KWSAPOEFX REGISTRY "KWSApoEFX.rgs" + +// ICON +IDI_EFFECT_ICON RCDATA "KWSApo.png" + diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rgs b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rgs new file mode 100644 index 00000000..b89d2a41 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoDll.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'KWSApoDll' + 'KWSApoDll.DLL' + { + val AppID = s '%APPID%' + } + } +} diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.cpp b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.cpp new file mode 100644 index 00000000..5924cd36 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.cpp @@ -0,0 +1,599 @@ +// +// KWSApoEFX.cpp -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// Implementation of CKWSApoEFX +// + +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlsync.h> +#include <mmreg.h> + +#include <initguid.h> +#include <audioenginebaseapo.h> +#include <baseaudioprocessingobject.h> +#include <resource.h> + +#include <float.h> + +#include "KWSApo.h" +#include <devicetopology.h> +#include <CustomPropKeys.h> + +// Static declaration of the APO_REG_PROPERTIES structure +// associated with this APO. The number in <> brackets is the +// number of IIDs supported by this APO. If more than one, then additional +// IIDs are added at the end +#pragma warning (disable : 4815) +const AVRT_DATA CRegAPOProperties<1> CKWSApoEFX::sm_RegProperties( + __uuidof(KWSApoEFX), // clsid of this APO + L"CKWSApoEFX", // friendly name of this APO + L"Copyright (c) Microsoft Corporation", // copyright info + 1, // major version # + 0, // minor version # + __uuidof(IKWSApoEFX), // iid of primary interface + (APO_FLAG) (APO_FLAG_BITSPERSAMPLE_MUST_MATCH | APO_FLAG_FRAMESPERSECOND_MUST_MATCH), + DEFAULT_APOREG_MININPUTCONNECTIONS, + DEFAULT_APOREG_MAXINPUTCONNECTIONS, + DEFAULT_APOREG_MINOUTPUTCONNECTIONS, + DEFAULT_APOREG_MAXOUTPUTCONNECTIONS, + DEFAULT_APOREG_MAXINSTANCES + ); + + +#pragma AVRT_CODE_BEGIN +//------------------------------------------------------------------------- +// Description: +// +// Do the actual processing of data. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections +// ppInputConnections - [in] pointer to list of input APO_CONNECTION_PROPERTY pointers +// u32NumOutputConnections - [in] number of output connections +// ppOutputConnections - [in] pointer to list of output APO_CONNECTION_PROPERTY pointers +// +// Return values: +// +// void +// +// Remarks: +// +// This function processes data in a manner dependent on the implementing +// object. This routine can not fail and can not block, or call any other +// routine that blocks, or touch pagable memory. +// +STDMETHODIMP_(void) CKWSApoEFX::APOProcess( + UINT32 u32NumInputConnections, + APO_CONNECTION_PROPERTY** ppInputConnections, + UINT32 u32NumOutputConnections, + APO_CONNECTION_PROPERTY** ppOutputConnections) +{ + UNREFERENCED_PARAMETER(u32NumInputConnections); + UNREFERENCED_PARAMETER(u32NumOutputConnections); + + FLOAT32 *pf32InputFrames, *pf32OutputFrames; + + ATLASSERT(m_bIsLocked); + + // assert that the number of input and output connectins fits our registration properties + ATLASSERT(m_pRegProperties->u32MinInputConnections <= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MaxInputConnections >= u32NumInputConnections); + ATLASSERT(m_pRegProperties->u32MinOutputConnections <= u32NumOutputConnections); + ATLASSERT(m_pRegProperties->u32MaxOutputConnections >= u32NumOutputConnections); + + // check APO_BUFFER_FLAGS. + switch( ppInputConnections[0]->u32BufferFlags ) + { + case BUFFER_INVALID: + { + ATLASSERT(false); // invalid flag - should never occur. don't do anything. + break; + } + case BUFFER_VALID: + case BUFFER_SILENT: + { + // get input pointer to connection buffer + pf32InputFrames = reinterpret_cast<FLOAT32*>(ppInputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_READ_POINTER(pf32InputFrames) ); + + // get output pointer to connection buffer + pf32OutputFrames = reinterpret_cast<FLOAT32*>(ppOutputConnections[0]->pBuffer); + ATLASSERT( IS_VALID_TYPED_WRITE_POINTER(pf32OutputFrames) ); + + if (BUFFER_SILENT == ppInputConnections[0]->u32BufferFlags) + { + WriteSilence( pf32OutputFrames, + ppInputConnections[0]->u32ValidFrameCount, + GetSamplesPerFrame() ); + } + else + { + ProcessBuffer(pf32OutputFrames, pf32InputFrames, + ppInputConnections[0]->u32ValidFrameCount, + &m_FormatInfo); + + // we don't try to remember silence + ppOutputConnections[0]->u32BufferFlags = BUFFER_VALID; + } + + // Set the valid frame count. + ppOutputConnections[0]->u32ValidFrameCount = ppInputConnections[0]->u32ValidFrameCount; + + break; + } + default: + { + ATLASSERT(false); // invalid flag - should never occur + break; + } + } // switch + +} // APOProcess +#pragma AVRT_CODE_END + +//------------------------------------------------------------------------- +// Description: +// +// Parameters: +// +// pTime - [out] hundreds-of-nanoseconds +// +// Return values: +// +// S_OK on success, a failure code on failure +STDMETHODIMP CKWSApoEFX::GetLatency(HNSTIME* pTime) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + IF_TRUE_ACTION_JUMP(NULL == pTime, hr = E_POINTER, Exit); + + *pTime = 0; + +Exit: + return hr; +} + + +//------------------------------------------------------------------------- +// Description: +// +// Verifies that the APO is ready to process and locks its state if so. +// +// Parameters: +// +// u32NumInputConnections - [in] number of input connections attached to this APO +// ppInputConnections - [in] connection descriptor of each input connection attached to this APO +// u32NumOutputConnections - [in] number of output connections attached to this APO +// ppOutputConnections - [in] connection descriptor of each output connection attached to this APO +// +// Return values: +// +// S_OK Object is locked and ready to process. +// E_POINTER Invalid pointer passed to function. +// APOERR_INVALID_CONNECTION_FORMAT Invalid connection format. +// APOERR_NUM_CONNECTIONS_INVALID Number of input or output connections is not valid on +// this APO. +STDMETHODIMP CKWSApoEFX::LockForProcess(UINT32 u32NumInputConnections, + APO_CONNECTION_DESCRIPTOR** ppInputConnections, + UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections) +{ + ASSERT_NONREALTIME(); + HRESULT hr = S_OK; + + UNCOMPRESSEDAUDIOFORMAT uncompAudioFormat; + + // fill in the samples per frame for the output (since APO_FLAG_SAMPLESPERFRAME_MUST_MATCH is not selected) + // There are two potentially different samples per frame values here. The input, which will be interleaved + primary. + // And the output, which is just the primary. Because this is used for clearing the zeroing the output buffer, we're going + // to fill it in with the output samples per frame. ProcessBuffer has both. + hr = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&uncompAudioFormat); + IF_FAILED_JUMP(hr, Exit); + + m_u32SamplesPerFrame = uncompAudioFormat.dwSamplesPerFrame; + + hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections, + ppInputConnections, u32NumOutputConnections, ppOutputConnections); + IF_FAILED_JUMP(hr, Exit); + +Exit: + return hr; +} + +// The method that this long comment refers to is "Initialize()" +//------------------------------------------------------------------------- +// Description: +// +// Generic initialization routine for APOs. +// +// Parameters: +// +// cbDataSize - [in] the size in bytes of the initialization data. +// pbyData - [in] initialization data specific to this APO +// +// Return values: +// +// S_OK Successful completion. +// E_POINTER Invalid pointer passed to this function. +// E_INVALIDARG Invalid argument +// AEERR_ALREADY_INITIALIZED APO is already initialized +// +// Remarks: +// +// This method initializes the APO. The data is variable length and +// should have the form of: +// +// struct MyAPOInitializationData +// { +// APOInitBaseStruct APOInit; +// ... // add additional fields here +// }; +// +// If the APO needs no initialization or needs no data to initialize +// itself, it is valid to pass NULL as the pbyData parameter and 0 as +// the cbDataSize parameter. +// +// As part of designing an APO, decide which parameters should be +// immutable (set once during initialization) and which mutable (changeable +// during the lifetime of the APO instance). Immutable parameters must +// only be specifiable in the Initialize call; mutable parameters must be +// settable via methods on whichever parameter control interface(s) your +// APO provides. Mutable values should either be set in the initialize +// method (if they are required for proper operation of the APO prior to +// LockForProcess) or default to reasonable values upon initialize and not +// be required to be set before LockForProcess. +// +// Within the mutable parameters, you must also decide which can be changed +// while the APO is locked for processing and which cannot. +// +// All parameters should be considered immutable as a first choice, unless +// there is a specific scenario which requires them to be mutable; similarly, +// no mutable parameters should be changeable while the APO is locked, unless +// a specific scenario requires them to be. Following this guideline will +// simplify the APO's state diagram and implementation and prevent certain +// types of bug. +// +// If a parameter changes the APOs latency or MaxXXXFrames values, it must be +// immutable. +// +// The default version of this function uses no initialization data, but does verify +// the passed parameters and set the m_bIsInitialized member to true. +// +// Note: This method may not be called from a real-time processing thread. +// + +HRESULT CKWSApoEFX::Initialize(UINT32 cbDataSize, BYTE* pbyData) +{ + HRESULT hr = S_OK; + CComPtr<IMMDevice> spMyDevice; + CComPtr<IDeviceTopology> spMyDeviceTopology; + CComPtr<IConnector> spMyConnector; + CComPtr<IPart> spPart; + UINT myPartId; + CComPtr<IKsControl> spKsControl; + ULONG cbReturned = 0; + + IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit); + IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_INVALIDARG, Exit); + + if (cbDataSize == sizeof(APOInitSystemEffects2)) + { + // + // Initialize for mode-specific signal processing + // + APOInitSystemEffects2* papoSysFxInit2 = (APOInitSystemEffects2*)pbyData; + KSP_PIN ksPinProperty; + + // Save reference to the effects property store. This saves effects settings + // and is the communication medium between this APO and any associated UI. + m_spAPOSystemEffectsProperties = papoSysFxInit2->pAPOSystemEffectsProperties; + + // Windows should pass a valid collection. + ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr); + IF_TRUE_ACTION_JUMP(papoSysFxInit2->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit); + + // Get the IDeviceTopology and IConnector interfaces to communicate with this + // APO's counterpart audio driver. This can be used for any proprietary + // communication. + hr = papoSysFxInit2->pDeviceCollection->Item(papoSysFxInit2->nSoftwareIoDeviceInCollection, &spMyDevice); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDevice->Activate(__uuidof(IKsControl), CLSCTX_ALL, NULL, (void**)&spKsControl); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&spMyDeviceTopology); + IF_FAILED_JUMP(hr, Exit); + + hr = spMyDeviceTopology->GetConnector(papoSysFxInit2->nSoftwareIoConnectorIndex, &spMyConnector); + IF_FAILED_JUMP(hr, Exit); + + spPart = spMyConnector; + + hr = spPart->GetLocalId(&myPartId); + IF_FAILED_JUMP(hr, Exit); + + ::ZeroMemory(&ksPinProperty, sizeof(ksPinProperty)); + ksPinProperty.Property.Set = KSPROPSETID_InterleavedAudio; + ksPinProperty.Property.Id = KSPROPERTY_INTERLEAVEDAUDIO_FORMATINFORMATION; + ksPinProperty.Property.Flags = KSPROPERTY_TYPE_GET; + ksPinProperty.PinId = myPartId & 0x0000ffff; + + ::ZeroMemory(&m_FormatInfo, sizeof(m_FormatInfo)); + + hr = spKsControl->KsProperty(&(ksPinProperty.Property), sizeof(ksPinProperty), &m_FormatInfo, sizeof(m_FormatInfo), &cbReturned); + IF_FAILED_JUMP(hr, Exit); + + IF_TRUE_ACTION_JUMP( m_FormatInfo.Size != sizeof(m_FormatInfo), hr = E_INVALIDARG, Exit); + } + else + { + // Invalid initialization size + hr = E_INVALIDARG; + goto Exit; + } + + // + // Register for notification of registry updates + // + hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)); + IF_FAILED_JUMP(hr, Exit); + + hr = m_spEnumerator->RegisterEndpointNotificationCallback(this); + IF_FAILED_JUMP(hr, Exit); + + m_bIsInitialized = true; + + +Exit: + return hr; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::GetEffectsList(_Outptr_result_buffer_maybenull_(*pcEffects) LPGUID *ppEffectsIds, _Out_ UINT *pcEffects, _In_ HANDLE Event) +{ + UNREFERENCED_PARAMETER(Event); + + *ppEffectsIds = NULL; + *pcEffects = 0; + + return S_OK; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::IsInputFormatSupported(IAudioMediaType *pOutputFormat, IAudioMediaType *pRequestedInputFormat, IAudioMediaType **ppSupportedInputFormat) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompInputFormat; + IAudioMediaType *recommendedFormat = NULL; + UINT totalChannelCount = (m_FormatInfo.PrimaryChannelCount + m_FormatInfo.InterleavedChannelCount); + + IF_TRUE_ACTION_JUMP((NULL == pRequestedInputFormat) || (NULL == ppSupportedInputFormat), hResult = E_POINTER, Exit); + *ppSupportedInputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the output + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported( pOutputFormat, pRequestedInputFormat, &recommendedFormat, true ); + IF_FAILED_JUMP(hResult, Exit); + + // If the input format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompInputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // the expected input channel count, for interleaved audio, is the total number of channels + // reported in the interleaved format information. Fail any request for a format that doesn't + // meet that requirement. + if (uncompInputFormat.dwSamplesPerFrame != totalChannelCount) + { + hResult = APOERR_FORMAT_NOT_SUPPORTED; + goto Exit; + } + + // If the requested format exactly matched our requirements, + // just return it. + if(!formatChanged) + { + *ppSupportedInputFormat = pRequestedInputFormat; + (*ppSupportedInputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different than the input, copy it and return S_FALSE; + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompInputFormat, ppSupportedInputFormat); + IF_FAILED_JUMP(hResult, Exit); + + hResult = S_FALSE; + } + +Exit: + + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::IsOutputFormatSupported(IAudioMediaType *pInputFormat, IAudioMediaType *pRequestedOutputFormat, IAudioMediaType **ppSupportedOutputFormat) +{ + ASSERT_NONREALTIME(); + bool formatChanged = false; + HRESULT hResult; + UNCOMPRESSEDAUDIOFORMAT uncompOutputFormat; + IAudioMediaType *recommendedFormat = NULL; + + IF_TRUE_ACTION_JUMP((NULL == pRequestedOutputFormat) || (NULL == ppSupportedOutputFormat), hResult = E_POINTER, Exit); + *ppSupportedOutputFormat = NULL; + + // Initial comparison to make sure the requested format is valid and consistent with the input + // format. Because of the APO flags specified during creation, the samples per frame value will + // not be validated. + hResult = IsFormatTypeSupported( pInputFormat, pRequestedOutputFormat, &recommendedFormat, true ); + IF_FAILED_JUMP(hResult, Exit); + + // If the output format is changed, make sure we track it for our return code. + if (S_FALSE == hResult) + { + formatChanged = true; + } + + // now retrieve the format that IsFormatTypeSupported decided on, building upon that by adding + // our channel count constraint. + hResult = recommendedFormat->GetUncompressedAudioFormat(&uncompOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + + // The expected output channel count is the number of primary channels in the interleaved data. + // We're removing the interleaved data. + if (uncompOutputFormat.dwSamplesPerFrame != m_FormatInfo.PrimaryChannelCount) + { + uncompOutputFormat.dwSamplesPerFrame = m_FormatInfo.PrimaryChannelCount; + uncompOutputFormat.dwChannelMask = m_FormatInfo.PrimaryChannelMask; + formatChanged = true; + } + + // If the requested format exactly matched our requirements, + // just return it. + if(!formatChanged) + { + *ppSupportedOutputFormat = pRequestedOutputFormat; + (*ppSupportedOutputFormat)->AddRef(); + hResult = S_OK; + } + else // we're proposing something different, copy it and return S_FALSE; + { + hResult = CreateAudioMediaTypeFromUncompressedAudioFormat(&uncompOutputFormat, ppSupportedOutputFormat); + IF_FAILED_JUMP(hResult, Exit); + hResult = S_FALSE; + } + +Exit: + + if (recommendedFormat) + { + recommendedFormat->Release(); + } + + return hResult; +} + +//------------------------------------------------------------------------- +// Description: +// +// +// +// Parameters: +// +// +// +// Return values: +// +// +// +// Remarks: +// +// +STDMETHODIMP CKWSApoEFX::GetInputChannelCount(UINT32 *pu32ChannelCount) +{ + ASSERT_NONREALTIME(); + HRESULT hResult = S_OK; + + IF_TRUE_ACTION_JUMP(!m_bIsInitialized, hResult = APOERR_NOT_INITIALIZED, Exit); + IF_TRUE_ACTION_JUMP(NULL == pu32ChannelCount, hResult = E_POINTER, Exit); + + // the input channel count is always the sum of the primary and interleaved + *pu32ChannelCount = (m_FormatInfo.PrimaryChannelCount + m_FormatInfo.InterleavedChannelCount); + +Exit: + return hResult; +} // GetChannelCount + +//------------------------------------------------------------------------- +// Description: +// +// Destructor. +// +// Parameters: +// +// void +// +// Return values: +// +// void +// +// Remarks: +// +// This method deletes whatever was allocated. +// +// This method may not be called from a real-time processing thread. +// +CKWSApoEFX::~CKWSApoEFX(void) +{ + // + // unregister for callbacks + // + if (m_bIsInitialized) + { + m_spEnumerator->UnregisterEndpointNotificationCallback(this); + } +} // ~CKWSApoEFX diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.rgs b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.rgs new file mode 100644 index 00000000..dc5bd41a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoEfx.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {9D89F614-F9D6-40DD-9F21-5E69FA3981ED} = s 'KWSApoEFX Class' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Both' + } + } + } +} diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoInterface.idl b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoInterface.idl new file mode 100644 index 00000000..6c0c98ad --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/KWSApoInterface.idl @@ -0,0 +1,21 @@ +// +// KWSApoInterface.idl -- Copyright (c) Microsoft Corporation. All rights reserved. +// +// Description: +// +// The interface and type definitions for KWS APO functionality. +// +import "oaidl.idl"; +import "ocidl.idl"; +import "audioenginebaseapo.idl"; + + +[ + object, + uuid(CF5C2AA7-68A8-4FD1-B86F-EBC008AD1B6F), + pointer_default(unique) +] +interface IKWSApoEFX : IUnknown +{ +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/Apo/kws/Resource.h b/audio/SoundWire/Samples/SdcaVad/Apo/kws/Resource.h new file mode 100644 index 00000000..df1260e1 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Apo/kws/Resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by KWSApoDll.rc +// +#define IDS_PROJNAME 100 +#define IDR_KWSAPODLL 101 +#define IDR_KWSAPOEFX 110 +#define IDI_EFFECT_ICON 200 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 132 +#endif +#endif diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.cpp b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.cpp new file mode 100644 index 00000000..8a8ec90d --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.cpp @@ -0,0 +1,211 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "stdafx.h" + +#include <strsafe.h> +#include <mfapi.h> + +#include <initguid.h> +#include "EventDetectorContosoAdapter.h" +#include "ContosoEventDetector.h" +#include <wrl.h> + +using namespace Microsoft::WRL; + +class EventDetectorContosoAdapter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IEventDetectorOemAdapter> +{ +public: + EventDetectorContosoAdapter() + { + } + + STDMETHODIMP GetCapabilities( + _Out_ EVENTFEATURES* GlobalFeatureSupport, + _Outptr_ LANGID** LangIds, + _Out_ ULONG* NumLanguages, + _Out_ ULONG* NumUserRecordings, + _Outptr_ WAVEFORMATEX** ppFormat) + { + const WAVEFORMATEX waveFormat = { WAVE_FORMAT_PCM, 1, 16000, 32000, 2, 16, 0 }; + + *ppFormat = (WAVEFORMATEX *)CoTaskMemAlloc(sizeof(WAVEFORMATEX)); + if (*ppFormat == nullptr) + { + return E_OUTOFMEMORY; + } + + memcpy(*ppFormat, &waveFormat, sizeof(WAVEFORMATEX)); + + *GlobalFeatureSupport = EVENTFEATURES_NoEventFeatures; + + *LangIds = (LANGID *)CoTaskMemAlloc(sizeof(LANGID)); + + if (*LangIds == nullptr) + { + return E_OUTOFMEMORY; + } + + **LangIds = 0x0409; + *NumLanguages = 1; + *NumUserRecordings = 0; + + return S_OK; + } + + STDMETHODIMP GetCapabilitiesForLanguage( + _In_ LANGID LangId, + _Outptr_ DETECTIONEVENT** EventIds, + _Out_ ULONG* NumEvents) + { + if (LangId == 0x0409) + { + DETECTIONEVENT events[] = { { CONTOSO_KEYWORD1, EVENTFEATURES_NoEventFeatures, {0}, L"Contoso 1", TRUE }, + { CONTOSO_KEYWORD2, EVENTFEATURES_NoEventFeatures, {0}, L"Contoso 2", TRUE } }; + + *EventIds = (DETECTIONEVENT *)CoTaskMemAlloc(sizeof(events)); + if (*EventIds == nullptr) + { + return E_OUTOFMEMORY; + } + + memcpy(*EventIds, &events, sizeof(events)); + *NumEvents = 2; + } + else + { + return E_INVALIDARG; + } + + return S_OK; + } + + STDMETHODIMP VerifyUserEventData( + _In_ IStream* ModelData, + _In_ WAVEFORMATEX* UserRecording, + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ LONG EventEndBytePos) + { + UNREFERENCED_PARAMETER(ModelData); + UNREFERENCED_PARAMETER(UserRecording); + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventEndBytePos); + + return E_NOTIMPL; + } + + STDMETHODIMP ComputeAndAddUserModelData( + _Inout_ IStream* ModelData, + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ LONG* EventEndBytePos, + _In_ WAVEFORMATEX** UserRecordings, + _In_ ULONG NumUserRecordings) + { + UNREFERENCED_PARAMETER(ModelData); + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventEndBytePos); + UNREFERENCED_PARAMETER(UserRecordings); + UNREFERENCED_PARAMETER(NumUserRecordings); + + return E_NOTIMPL; + } + + STDMETHODIMP BuildArmingPatternData( + _In_ IStream* UserModelData, + _In_ DETECTIONEVENTSELECTOR* EventSelectors, + _In_ ULONG NumEventSelectors, + _Outptr_ SOUNDDETECTOR_PATTERNHEADER** ppPatternData) + { + CONTOSO_KEYWORDCONFIGURATION *pPatternData = nullptr; + + UNREFERENCED_PARAMETER(UserModelData); + + if (NumEventSelectors > 2) + { + return E_INVALIDARG; + } + + if ((EventSelectors[0].Event.EventId != CONTOSO_KEYWORD1 && EventSelectors[0].Event.EventId != CONTOSO_KEYWORD2) || + (EventSelectors[0].UserId != 0) || (EventSelectors[0].LangId != 0x0409)) + { + return E_INVALIDARG; + } + + pPatternData = (CONTOSO_KEYWORDCONFIGURATION*)CoTaskMemAlloc(sizeof(CONTOSO_KEYWORDCONFIGURATION)); + if (pPatternData == nullptr) + { + return E_OUTOFMEMORY; + } + + pPatternData->Header.Size = sizeof(*pPatternData); + pPatternData->Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + pPatternData->ContosoDetectorConfigurationData = 0x12345678; + + *ppPatternData = &pPatternData->Header; + pPatternData = nullptr; + + return S_OK; + } + + STDMETHODIMP ParseDetectionResultData( + _In_ IStream* UserModelData, + _In_ SOUNDDETECTOR_PATTERNHEADER* Result, + _Outptr_ SOUNDDETECTOR_PATTERNHEADER** AssistantContext, + _Out_ DETECTIONEVENTSELECTOR* EventSelector, + _Out_ EVENTACTION* EventAction, + _Out_ ULONG64* EventStartPerformanceCounterValue, + _Out_ ULONG64* EventEndPerformanceCounterValue, + _Outptr_ WCHAR** DebugOutput) + { + const CONTOSO_KEYWORDDETECTIONRESULT *contosoResult; + + UNREFERENCED_PARAMETER(UserModelData); + + if (Result->PatternType != CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2 || Result->Size < sizeof(CONTOSO_KEYWORDDETECTIONRESULT)) + { + return E_INVALIDARG; + } + + contosoResult = (CONTOSO_KEYWORDDETECTIONRESULT*)Result; + + if (CONTOSO_KEYWORD1 == contosoResult->EventId) + { + wcscpy_s(EventSelector->Event.DisplayName, L"Contoso 1"); + } + else if (CONTOSO_KEYWORD2 == contosoResult->EventId) + { + wcscpy_s(EventSelector->Event.DisplayName, L"Contoso 2"); + } + else + { + return E_INVALIDARG; + } + + // Fill in event action information for the actual detection, based on what has been armed. + EventSelector->Event.EventId = contosoResult->EventId; + EventSelector->Armed = TRUE; + EventSelector->UserId = 0; + EventSelector->LangId = 0x0409; + + EventAction->EventdActionType = EVENTACTIONTYPE_Accept; + EventAction->EventActionContextType = EVENTACTIONCONTEXTTYPE_None; + + // Retrieve the event start/stop times for the payload + *EventStartPerformanceCounterValue = contosoResult->KeywordStartTimestamp; + *EventEndPerformanceCounterValue = contosoResult->KeywordStopTimestamp; + + *AssistantContext = nullptr; + *DebugOutput = nullptr; + + return S_OK; + } + + STDMETHODIMP_(void) ReportOSDetectionResult( + _In_ DETECTIONEVENTSELECTOR EventSelector, + _In_ EVENTACTION EventAction) + { + UNREFERENCED_PARAMETER(EventSelector); + UNREFERENCED_PARAMETER(EventAction); + } +}; + +CoCreatableClass(EventDetectorContosoAdapter); + diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.def b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.def new file mode 100644 index 00000000..ddeb3eac --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.def @@ -0,0 +1,6 @@ +LIBRARY + +EXPORTS + DllGetActivationFactory PRIVATE + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.idl b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.idl new file mode 100644 index 00000000..9289fba5 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.idl @@ -0,0 +1,20 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +import "oaidl.idl"; +import "ocidl.idl"; + +import "EventDetectorOemAdapter.idl"; + +[uuid(33C3430A-6199-4C55-831F-30EDF9D644EB), version(1.0)] +library EventDetectorContosoAdapterLib +{ + // The class's uuid (i.e. the COM CLSID) must match that of the pattern + // type GUID returned by the audio driver + // 0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9 + [uuid(207F3D0C-5C79-496F-A94C-D3D2934DBFA9), version(1.0)] + coclass EventDetectorContosoAdapter + { + [default] interface IEventDetectorOemAdapter; + } +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.rc b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.rc new file mode 100644 index 00000000..d871dd72 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.rc @@ -0,0 +1,13 @@ +#if 0 +Copyright (c) Microsoft Corporation. All Rights Reserved +#endif + +#include "winres.h" +#include <ntverp.h> +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Contoso event detector adapter" +#define VER_INTERNALNAME_STR "EventDetectorContosoAdapter" +#define VER_ORIGINALFILENAME_STR "EventDetectorContosoAdapter.dll" +#include <Common.ver> +
\ No newline at end of file diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj new file mode 100644 index 00000000..10231100 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj @@ -0,0 +1,433 @@ +<?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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{C1851F27-BDAA-4DF1-8CA5-9D0176FD2B33}</SampleGuid> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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> + <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|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <TargetName>EventDetectorContosoAdapter</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <ClCompile> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary> + <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);_WINDLL;_USRDLL;UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);Kernel32.lib;ole32.lib;oleaut32.lib;advapi32.lib;user32.lib;uuid.lib;mfplat.lib;runtimeobject.lib</AdditionalDependencies> + <ModuleDefinitionFile>EventDetectorContosoAdapter.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="EventDetectorContosoAdapter.cpp" /> + <ClCompile Include="stdafx.cpp" /> + <Midl Include="EventDetectorContosoAdapter.idl" /> + <ResourceCompile Include="EventDetectorContosoAdapter.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj.Filters new file mode 100644 index 00000000..6637ef91 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/EventDetectorContosoAdapter.vcxproj.Filters @@ -0,0 +1,17 @@ +<?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> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/dllmain.cpp b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/dllmain.cpp new file mode 100644 index 00000000..39c15c7b --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/dllmain.cpp @@ -0,0 +1,35 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "stdafx.h" +#include <wrl\module.h> + +using namespace Microsoft::WRL; + +#if !defined(__WRL_CLASSIC_COM__) +STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory) +{ + return Module<InProc>::GetModule().GetActivationFactory(activatibleClassId, factory); +} +#endif + +#if !defined(__WRL_WINRT_STRICT__) +_Check_return_ +STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) +{ + return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv); +} +#endif + +__control_entrypoint(DllExport) +STDAPI DllCanUnloadNow() +{ + return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE; +} + +STDAPI_(BOOL) DllMain(_In_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) +{ + if (reason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(hinst); + } + return TRUE; +} diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.cpp b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.cpp new file mode 100644 index 00000000..cf76439a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.cpp @@ -0,0 +1,6 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.h b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.h new file mode 100644 index 00000000..6ed512c8 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/stdafx.h @@ -0,0 +1,13 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include "targetver.h" + +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include <windows.h> + + + +// TODO: reference additional headers your program requires here diff --git a/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/targetver.h b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/targetver.h new file mode 100644 index 00000000..847309f2 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/EventDetectorAdapter/targetver.h @@ -0,0 +1,10 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include <SDKDDKVer.h> diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/AudioFormats.h b/audio/SoundWire/Samples/SdcaVad/Inc/AudioFormats.h new file mode 100644 index 00000000..d93dcf19 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/AudioFormats.h @@ -0,0 +1,623 @@ +/*++ + +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: + + AudioFormats.h + +Abstract: + + Contains Audio formats supported for the SDCAVad Device + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// +// Basic-testing formats. +// +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2 = +{ + { + 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) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2nomask = +{ + { + 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, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2 = +{ + { + 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) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 352800, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c2_24in32_nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 44100, + 352800, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2_24in32 = +{ + { + 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) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2_24in32_nomask = +{ + { + 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) + }, + 24, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +// No Mask version is used for 2ch Capture, where the mask is not meaningful +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c2nomask = +{ + { + 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, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm96000c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 96000, + 768000, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm96000c2 = +{ + { + 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 Pcm192000c2_24in32 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 1536000, + 8, + 32, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 24, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm192000c2 = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 192000, + 768000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + KSAUDIO_SPEAKER_STEREO, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + + + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm44100c1 = +{ + { + 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) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c1 = +{ + { + 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) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm48000c4nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 4, + 48000, + 384000, + 8, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c2nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 2, + 16000, + 64000, + 4, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +static +KSDATAFORMAT_WAVEFORMATEXTENSIBLE Pcm16000c4nomask = +{ + { + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + { + { + WAVE_FORMAT_EXTENSIBLE, + 4, + 16000, + 128000, + 8, + 16, + sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) + }, + 16, + 0, + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) + } +}; + +PAGED_CODE_SEG +inline +NTSTATUS +SdcaVad_RetrieveOrCreateDataFormatList( + _In_ ACXPIN Pin, + _In_ PGUID Mode, + _Out_ ACXDATAFORMATLIST * FormatList +) +{ + PAGED_CODE(); + + // Note: AcxPinGetRawDataFormatList will do the same thing as AcxPinRetrieveModeDataFormatList(RAW) + NTSTATUS status = AcxPinRetrieveModeDataFormatList(Pin, Mode, FormatList); + if (!NT_SUCCESS(status)) + { + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Pin; + + ACX_DATAFORMAT_LIST_CONFIG config; + ACX_DATAFORMAT_LIST_CONFIG_INIT(&config); + + status = AcxDataFormatListCreate(AcxCircuitGetWdfDevice(AcxPinGetCircuit(Pin)), &attributes, &config, FormatList); + + if (NT_SUCCESS(status)) + { + status = AcxPinAssignModeDataFormatList(Pin, Mode, *FormatList); + } + } + return status; +} + +PAGED_CODE_SEG +inline +NTSTATUS +SdcaVad_ClearDataFormatList( + _In_ ACXDATAFORMATLIST FormatList +) +{ + PAGED_CODE(); + + ACX_DATAFORMAT_LIST_ITERATOR formatIter; + ACXDATAFORMAT format; + ACXDATAFORMAT formatToDelete = nullptr; + NTSTATUS status = STATUS_SUCCESS; + + // The AcxDataFormatListRemoveDataFormats API is not available in ACX 1.0 + ACX_DATAFORMAT_LIST_ITERATOR_INIT(&formatIter); + AcxDataFormatListBeginIteration(FormatList, &formatIter); + status = AcxDataFormatListRetrieveNextFormat(FormatList, &formatIter, &format); + while (NT_SUCCESS(status) && format != nullptr) + { + // We can delete this format after we've retrieved the next format + formatToDelete = format; + status = AcxDataFormatListRetrieveNextFormat(FormatList, &formatIter, &format); + if (!NT_SUCCESS(status)) + { + format = nullptr; + } + + status = AcxDataFormatListRemoveDataFormat(FormatList, formatToDelete); + if (!NT_SUCCESS(status)) + { + break; + } + + } + AcxDataFormatListEndIteration(FormatList, &formatIter); + + if (status == STATUS_NO_MORE_ENTRIES) + { + status = STATUS_SUCCESS; + } + + return status; +} + +PAGED_CODE_SEG +inline +NTSTATUS +SdcaVad_CopyFormats( + _In_ ACXDATAFORMATLIST SourceList, + _In_ ACXDATAFORMATLIST DestinationList, + _Out_ PULONG FormatCount +) +{ + PAGED_CODE(); + + ACX_DATAFORMAT_LIST_ITERATOR formatIter; + ACXDATAFORMAT format; + NTSTATUS status = STATUS_SUCCESS; + + *FormatCount = 0; + + // Now copy over all formats from the target pin + ACX_DATAFORMAT_LIST_ITERATOR_INIT(&formatIter); + AcxDataFormatListBeginIteration(SourceList, &formatIter); + while (NT_SUCCESS(status) && NT_SUCCESS(AcxDataFormatListRetrieveNextFormat(SourceList, &formatIter, &format))) + { + ++*FormatCount; + + // The DataFormatList adds a reference to the format object + status = AcxDataFormatListAddDataFormat(DestinationList, format); + } + AcxDataFormatListEndIteration(SourceList, &formatIter); + + // Then finally assign the default format + ACXDATAFORMAT defaultFormat; + if (NT_SUCCESS(status) && NT_SUCCESS(AcxDataFormatListRetrieveDefaultDataFormat(SourceList, &defaultFormat))) + { + status = AcxDataFormatListAssignDefaultDataFormat(DestinationList, defaultFormat); + } + + return status; +} diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/ContosoEventDetector.h b/audio/SoundWire/Samples/SdcaVad/Inc/ContosoEventDetector.h new file mode 100644 index 00000000..ca73daa4 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/ContosoEventDetector.h @@ -0,0 +1,51 @@ +/*++ + +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: + + ContosoEventDetector.h + +Abstract: + + Sample event detector definitions + +Environment: + + Kernel mode + +--*/ + + +#pragma once + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorConfigurationData; +} CONTOSO_KEYWORDCONFIGURATION; + +typedef struct +{ + SOUNDDETECTOR_PATTERNHEADER Header; + LONGLONG ContosoDetectorResultData; + ULONGLONG KeywordStartTimestamp; + ULONGLONG KeywordStopTimestamp; + GUID EventId; +} CONTOSO_KEYWORDDETECTIONRESULT; + +DEFINE_GUID(CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2, +0x207f3d0c, 0x5c79, 0x496f, 0xa9, 0x4c, 0xd3, 0xd2, 0x93, 0x4d, 0xbf, 0xa9); + +// {A537F559-2D67-463B-B10E-BEB750A21F31} +DEFINE_GUID(CONTOSO_KEYWORD1, +0xa537f559, 0x2d67, 0x463b, 0xb1, 0xe, 0xbe, 0xb7, 0x50, 0xa2, 0x1f, 0x31); +// {655E417A-80A5-4A77-B3F1-512EAF67ABCF} +DEFINE_GUID(CONTOSO_KEYWORD2, +0x655e417a, 0x80a5, 0x4a77, 0xb3, 0xf1, 0x51, 0x2e, 0xaf, 0x67, 0xab, 0xcf); + diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/NewDelete.h b/audio/SoundWire/Samples/SdcaVad/Inc/NewDelete.h new file mode 100644 index 00000000..94e6f1e9 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/NewDelete.h @@ -0,0 +1,121 @@ +/*++ + +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_ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <wdm.h> + +#ifdef __cplusplus +} +#endif + +// Pool tag used for SDCA sample allocations +#define DEFAULT_POOLTAG 'wNwS' + +/***************************************************************************** +* 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/SoundWire/Samples/SdcaVad/Inc/SdcaVXuTestInterface.h b/audio/SoundWire/Samples/SdcaVad/Inc/SdcaVXuTestInterface.h new file mode 100644 index 00000000..eac37c3e --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/SdcaVXuTestInterface.h @@ -0,0 +1,55 @@ +/*++ + +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: + + SdcaVXuTestInterface.h + +Abstract: + + Contains definitions to allow user mode applications to communicate + directly with private interface of SdcaVXu driver + +Environment: + + Kernel mode, User mode + +--*/ + +#pragma once + +// The SDCA XU Driver can add a device interface to any of the raw PDOs it creates. +// +// We'll add the GUID_DEVINTERFACE_SDCAVXU_TEST_RAWCONTROL to the initial raw PDO +// the XU driver creates (which currently isn't used for any other purpose). +// +// User-mode applications can then use this device interface to find the target +// for IOCTL requests that are intended for the XU driver. +// +// A real XU driver could add a device interface to the initial raw PDO or to +// any of the Circuit Devices it creates to support the XU driver circuits, or +// it could use WdfControlDeviceInitAllocate to create a Control Device Object +// to accept IOCTL requests from user mode (though a Control Device Object +// cannot be used with WdfDeviceCreateDeviceInterface and would instead be +// used with WdfDeviceCreateSymbolicLink) +// +// A real XU driver could also use WdfDeviceInitAssignName to enable user-mode +// applications to call CreateFile for the device. + +// {48124666-FA50-47DE-A72D-0833510DBF96} +DEFINE_GUID(GUID_DEVINTERFACE_SDCAVXU_TEST_RAWCONTROL, +0x48124666, 0xfa50, 0x47de, 0xa7, 0x2d, 0x8, 0x33, 0x51, 0xd, 0xbf, 0x96); + +typedef struct _SDCAVXU_TEST_DATA +{ + ULONG Data; +} SDCAVXU_TEST_DATA, *PSDCAVXU_TEST_DATA; + +#define IOCTL_SDCAVXU_INTERFACE_TEST \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/TestProperties.h b/audio/SoundWire/Samples/SdcaVad/Inc/TestProperties.h new file mode 100644 index 00000000..1963ca44 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/TestProperties.h @@ -0,0 +1,60 @@ +/*++ + +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: + + TestProperties.h + +Abstract: + + Contains Test property values + +Environment: + + Kernel mode + +--*/ + +#pragma once + +const ULONG _DSP_STREAM_PROPERTY_UI4_VALUE = 1; + +// +// VENDOR SPECIFIC DATA +// These are made up placeholders to demonstrate how the KSPROPERTY_SDCA_VENDOR_SPECIFIC works +typedef struct _VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL +{ + ULONG VendorSpecificId; + ULONG VendorSpecificSize; + union + { + struct TestData + { + ULONG EndpointId; + ULONG DataPort; + } Data; + struct TestConfig + { + BOOLEAN IsScatterGather; + } Config; + }; +} VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL, * PVIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL; + +typedef struct _VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA +{ + ULONG Test1; + ULONG Test2; +} VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA, * PVIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA; + +enum VIRTUAL_STACK_VENDOR_SPECIFIC_REQUEST +{ + VirtualStackVendorSpecificRequestGetTestData, + VirtualStackVendorSpecificRequestSetTestConfig +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/cpp_utils.h b/audio/SoundWire/Samples/SdcaVad/Inc/cpp_utils.h new file mode 100644 index 00000000..f4ed6220 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/cpp_utils.h @@ -0,0 +1,71 @@ +/*++ + +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: + + cpp_utils.h + +Abstract: + + Contains CPP utilities + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// Function scope_exit instantiates scope_exit object +// Constructor accepts lamda as parameter. +// Assign tasks in lamdba to be executed on scope exit. +template <typename F> +auto scope_exit(F f) +{ + class scope_exit + { + public: + scope_exit(F f) : + _f{ f } + { + } + + ~scope_exit() + { + if (_call) + { + _f(); + } + } + + // Ensures the scope_exit lambda will not be called + void release() + { + _call = false; + } + + // Executes the scope_exit lambda immediately if not yet run; ensures it will not run again + void reset() + { + if (_call) + { + _f(); + _call = false; + } + } + + private: + F _f; + bool _call = true; + }; + + return scope_exit{ f }; +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/Inc/trace_macros.h b/audio/SoundWire/Samples/SdcaVad/Inc/trace_macros.h new file mode 100644 index 00000000..c2188dc6 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Inc/trace_macros.h @@ -0,0 +1,460 @@ +#pragma once + +#include <stdarg.h> // for va_start, etc. + +#pragma region Tracing level definitions + +#if !defined(FAILED_NTSTATUS) +#define FAILED_NTSTATUS(status) (((NTSTATUS)(status)) < 0) +#endif + +#if !defined(SUCCEEDED_NTSTATUS) +#define SUCCEEDED_NTSTATUS(status) (((NTSTATUS)(status)) >= 0) +#endif + +//! Define shorter versions of the ETW trace levels +#define LEVEL_CRITICAL TRACE_LEVEL_CRITICAL +#define LEVEL_ERROR TRACE_LEVEL_ERROR +#define LEVEL_WARNING TRACE_LEVEL_WARNING +#define LEVEL_INFO TRACE_LEVEL_INFORMATION +#define LEVEL_VERBOSE TRACE_LEVEL_VERBOSE + +//! This is a special LEVEL that changes the trace macro level from ERROR to VERBOSE +//! depending on whether the return value passed to the macro was non-zero or zero, +//! respectively. +#define LEVEL_COND 0xFF +#pragma endregion + +//! Logger and Enabled that supports both level and flag. +//! \link https://msdn.microsoft.com/en-us/library/windows/hardware/ff542492(v=vs.85).aspx +#define WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) WPP_LEVEL_LOGGER(FLAGS) +#define WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) (WPP_LEVEL_ENABLED(FLAGS) && (WPP_CONTROL(WPP_BIT_ ## FLAGS).Level >= LEVEL)) + +//! This macro is to be used by the WPP custom macros below that want to do conditional +//! logging based on return value. If LEVEL_VERBOSE is specified when calling a macro that +//! uses this, the level will be set to LEVEL_INFO if return code is 0 or +//! LEVEL_ERROR if the return code is not 0. This can be called in any PRE macro. +//! +//! The "LEVEL == LEVEL_COND" check generates a compiler warning that the "conditional +//! expression is constant" so we explicitly disable that. +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + BOOL bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED(HR)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + +#define WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + BOOLEAN bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS); \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4127)) \ + if (LEVEL == LEVEL_COND) \ + { \ + if (SUCCEEDED_NTSTATUS(STATUS)) \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_VERBOSE, FLAGS); \ + } \ + else \ + { \ + bEnabled = WPP_LEVEL_FLAGS_ENABLED(LEVEL_ERROR, FLAGS); \ + } \ + } \ + __pragma(warning(pop)) + + +#define WPP_LEVEL_FLAGS_IFRLOG_ENABLED(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_LOGGER(LEVEL, FLAGS, IFRLOG) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_ENABLED(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_IFRLOG_FLAGS_LOGGER(LEVEL, IFRLOG, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_HR_PRE(LEVEL, FLAGS, HR) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) +#define WPP_LEVEL_FLAGS_HR_POST(LEVEL, FLAGS, HR) ;} +#define WPP_LEVEL_FLAGS_HR_ENABLED(LEVEL, FLAGS, HR) bEnabled +#define WPP_LEVEL_FLAGS_HR_LOGGER(LEVEL, FLAGS, HR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETVAL_ENABLED(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETVAL_LOGGER(LEVEL, FLAGS, RETVAL) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_FI_ENABLED(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_FI_LOGGER(LEVEL, FLAGS, FI) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_STATUS_PRE(LEVEL, FLAGS, STATUS) { WPP_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) +#define WPP_LEVEL_FLAGS_STATUS_POST(LEVEL, FLAGS, STATUS) ;} +#define WPP_LEVEL_FLAGS_STATUS_ENABLED(LEVEL, FLAGS, STATUS) bEnabled +#define WPP_LEVEL_FLAGS_STATUS_LOGGER(LEVEL, FLAGS, STATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_PRE(LEVEL, FLAGS, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POST(LEVEL, FLAGS, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_ENABLED(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_LOGGER(LEVEL, FLAGS, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_PRE(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) do {\ +NTSTATUS __statusRet = (RETSTATUS);\ +if(__statusRet == ALLOWEDSTATUS)\ +{\ + __statusRet = STATUS_SUCCESS;\ +}\ +if (FAILED_NTSTATUS(__statusRet)) { +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_POST(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETPTR_PRE(LEVEL, FLAGS, RETPTR) do { if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETPTR_POST(LEVEL, FLAGS, RETPTR) ; return STATUS_INSUFFICIENT_RESOURCES; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETPTR_ENABLED(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETPTR_LOGGER(LEVEL, FLAGS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_PRE(LEVEL, FLAGS, RETSTATUS, RETPTR) do { NTSTATUS __statusRet = (RETSTATUS); if ((RETPTR) == nullptr) { +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_POST(LEVEL, FLAGS, RETSTATUS, RETPTR) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_ENABLED(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_RETPTR_LOGGER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_PRE(LEVEL, FLAGS, RETSTATUS, POSCOND) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_POST(LEVEL, FLAGS, RETSTATUS, POSCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_POSCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_PRE(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) do { NTSTATUS __statusRet = (RETSTATUS); if ((POSCOND)) { +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_POST(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ENABLED(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_LOGGER(LEVEL, FLAGS, IFRLOG, POSCOND, RETSTATUS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_PRE(LEVEL, FLAGS, RETSTATUS, NEGCOND) do { NTSTATUS __statusRet = (RETSTATUS); if (!(NEGCOND)) { +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_POST(LEVEL, FLAGS, RETSTATUS, NEGCOND) ; return __statusRet; } } while (0, 0) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_ENABLED(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) +#define WPP_LEVEL_FLAGS_RETSTATUS_NEGCOND_LOGGER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) + +#pragma region IFR Enablement Macros + +// Opt-in to a WPP recorder feature that enables independent evaluation of conditions to decide if a +// message needs to be sent to the recorder, an enabled session, or both. +#define ENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER 1 + +// Logger/Enabled macros used to decide if a message that is being sent to a custom recorder should +// also go to an enabled session. These do not depend on the custom recorder itself, so just +// delegate to the default. +#define WPP_IFRLOG_LEVEL_FLAGS_LOGGER(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_LOGGER(LEVEL, FLAGS) +#define WPP_IFRLOG_LEVEL_FLAGS_ENABLED(IFRLOG, LEVEL, FLAGS) WPP_LEVEL_FLAGS_ENABLED(LEVEL, FLAGS) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE(LEVEL, FLAGS, HR) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED(HR) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_CONDITIONAL_LEVEL_FLAGS_OVERRIDE_NTSTATUS(LEVEL, FLAGS, STATUS) \ + ((LEVEL == LEVEL_COND) ? \ + (FAILED_NTSTATUS(STATUS) ? \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_ERROR, FLAGS) : WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL_VERBOSE, FLAGS)) : \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS)) + +#define WPP_RECORDER_LEVEL_FLAGS_HR_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_HR_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETVAL_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_FI_ARGS(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_FI_FILTER(LEVEL, FLAGS, RETVAL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_ARGS(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_STATUS_FILTER(LEVEL, FLAGS, STATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_ARGS(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_FILTER(LEVEL, FLAGS, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_RETSTATUS_ALLOWEDSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, ALLOWEDSTATUS) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_ARGS(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETPTR_FILTER(LEVEL, FLAGS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_ARGS(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_RETPTR_FILTER(LEVEL, FLAGS, RETSTATUS, RETPTR) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_ARGS(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_POSCOND_FILTER(LEVEL, FLAGS, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_ARGS(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_IFRLOG_POSCOND_RETSTATUS_FILTER(LEVEL, FLAGS, IFRLOG, RETSTATUS, POSCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) + +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_ARGS(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, FLAGS) +#define WPP_RECORDER_LEVEL_FLAGS_RETSTATUS_NEGCOND_FILTER(LEVEL, FLAGS, RETSTATUS, NEGCOND) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, FLAGS) +#pragma endregion + +#pragma region Custom tracing macros + +// begin_wpp config +// USEPREFIX(DrvLogCritical, "%!STDPREFIX!CRIT: "); +// USEPREFIX(DrvLogError, "%!STDPREFIX!ERROR: "); +// USEPREFIX(DrvLogWarning, "%!STDPREFIX!WARN: "); +// USEPREFIX(DrvLogInfo, "%!STDPREFIX!INFO: "); +// USEPREFIX(DrvLogVerbose, "%!STDPREFIX!VERB: "); +// USEPREFIX(DrvLogEnter, "%!STDPREFIX!ENTER"); +// USEPREFIX(DrvLogExit, "%!STDPREFIX!EXIT"); +// end_wpp + +// begin_wpp config +// FUNC DrvLogCritical{LEVEL=TRACE_LEVEL_CRITICAL}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogError{LEVEL=TRACE_LEVEL_ERROR}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogWarning{LEVEL=TRACE_LEVEL_WARNING}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogInfo{LEVEL=TRACE_LEVEL_INFORMATION}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogEnter{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// FUNC DrvLogVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(IFRLOG,FLAGS,MSG,...); +// FUNC DrvLogExit{LEVEL=TRACE_LEVEL_VERBOSE,FLAGS=FLAG_FUNCTION}(IFRLOG,...); +// end_wpp + + +#ifdef __INTELLISENSE__ +#define FLAG_DEVICE_ALL 0x01 +#define FLAG_FUNCTION 0x02 +#define FLAG_INFO 0x04 +#define FLAG_PNP 0x08 +#define FLAG_POWER 0x10 +#define FLAG_STREAM 0x20 +#define FLAG_INIT 0x40 +#define FLAG_DDI 0x80 +#define FLAG_GENERIC 0x100 +void DrvLogCritical(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogError(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogWarning(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogInfo(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogEnter(void* log, ...); +void DrvLogVerbose(void* log, int flags, const WCHAR* fmt, ...); +void DrvLogExit(void* log, ...); + +void RETURN_NTSTATUS_IF_FAILED(NTSTATUS status); +void RETURN_NTSTATUS_IF_FAILED_MSG(NTSTATUS status, const WCHAR *fmt, ...); +void RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(NTSTATUS returnStatus, NTSTATUS allowedStatus); +void RETURN_NTSTATUS_IF_NULL_ALLOC(PVOID ptr); +void RETURN_NTSTATUS_IF_NULL(PVOID ptr); +void RETURN_NTSTATUS_IF_TRUE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS_IF_TRUE_MSG(BOOL condition, NTSTATUS status, const WCHAR *fmt, ...); +void RETURN_NTSTATUS_IF_FALSE(BOOL condition, NTSTATUS status); +void RETURN_NTSTATUS(NTSTATUS status); +void RETURN_NTSTATUS_MSG(NTSTATUS status, const WCHAR* fmt, ...); +#endif// __INTELLISENSE__ + +//********************************************************* +// MACRO: TRACE_METHOD_LINE +// +// begin_wpp config +// FUNC TRACE_METHOD_LINE(LEVEL, FLAGS, MSG, ...); +// USESUFFIX (TRACE_METHOD_LINE, ", this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_ENTRY +// +// begin_wpp config +// FUNC TRACE_METHOD_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_ENTRY, "Enter, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_METHOD_EXIT, "Exit, this=0x%p", this); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_METHOD_EXIT_HR, "Exit, this=0x%p, hr=%!HRESULT!", this, HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_DWORD, "Exit, this=0x%p, ret=0x%08Ix ", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_METHOD_EXIT_PTR,"Exit, this=0x%p, retptr=0x%p", this, RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_METHOD_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_METHOD_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_METHOD_EXIT_STATUS, "Exit, this=0x%p, status=%!STATUS!", this, STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_ENTRY +// +// begin_wpp config +// FUNC TRACE_FUNCTION_ENTRY(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_ENTRY, "Enter"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT(LEVEL, FLAGS); +// USESUFFIX (TRACE_FUNCTION_EXIT, "Exit"); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_HR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_HR(LEVEL, FLAGS, HR); +// USESUFFIX (TRACE_FUNCTION_EXIT_HR, "Exit, hr=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_DWORD +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_DWORD(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_DWORD, "Exit, ret=0x%08Ix", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_PTR +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_PTR(LEVEL, FLAGS, RETVAL); +// USESUFFIX (TRACE_FUNCTION_EXIT_PTR, "Exit, retptr=0x%p", RETVAL); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FUNCTION_EXIT_STATUS +// +// begin_wpp config +// FUNC TRACE_FUNCTION_EXIT_STATUS(LEVEL, FLAGS, STATUS); +// USESUFFIX (TRACE_FUNCTION_EXIT_STATUS, "Exit, status=%!STATUS!", STATUS); +// end_wpp + +//********************************************************* +// MACRO: TRACE_LINE +// +// begin_wpp config +// FUNC TRACE_LINE(LEVEL, FLAGS, MSG, ...); +// end_wpp + +//********************************************************* +// MACRO: TRACE_HRESULT +// +// begin_wpp config +// FUNC TRACE_HRESULT(LEVEL, FLAGS, HR, MSG, ...); +// USESUFFIX (TRACE_HRESULT, ", ret=%!HRESULT!", HR); +// end_wpp + +//********************************************************* +// MACRO: TRACE_FAILURE_INFO (WIL FailureInfo logging) +// see: https://github.com/microsoft/wil/blob/master/include/wil/result_macros.h +// +// begin_wpp config +// FUNC TRACE_FAILURE_INFO(LEVEL, FLAGS, FI); +// USESUFFIX(TRACE_FAILURE_INFO, " [%04X] '%ws', hr=%!HRESULT! ['%s' (%u)]", FI.threadId, FI.pszMessage, FI.hr, FI.pszFile, FI.uLineNumber); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(RETSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(RETSTATUS, MSG, ...); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_MSG, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_MSG, " - status=%!STATUS!",__statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(RETSTATUS, ALLOWEDSTATUS); +// USEPREFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, "%!STDPREFIX!ERROR:"); +// USESUFFIX(RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL_ALLOC +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL_ALLOC{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=STATUS_INSUFFICIENT_RESOURCES"); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_NULL +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_NULL{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, RETPTR); +// USESUFFIX(RETURN_NTSTATUS_IF_NULL, "status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(POSCOND, RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_TRUE_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_TRUE_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(POSCOND, RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_IF_TRUE_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_IF_FALSE +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_IF_FALSE{LEVEL=LEVEL_ERROR,FLAGS=DUMMY}(RETSTATUS, NEGCOND); +// USESUFFIX(RETURN_NTSTATUS_IF_FALSE, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS +// +// begin_wpp config +// FUNC RETURN_NTSTATUS{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(RETSTATUS); +// USESUFFIX(RETURN_NTSTATUS, " File:%s, Line:%d - status=%!STATUS!", __FILE__, __LINE__, __statusRet); +// end_wpp + +// MACRO: RETURN_NTSTATUS_MSG +// +// begin_wpp config +// FUNC RETURN_NTSTATUS_MSG{LEVEL=LEVEL_ERROR,FLAGS=FLAG_DEVICE_ALL,IFRLOG=g_SDCAVDspLog}(RETSTATUS, MSG, ...); +// USESUFFIX(RETURN_NTSTATUS_MSG, " - status=%!STATUS!", __statusRet); +// end_wpp + +#define W32 +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#pragma endregion diff --git a/audio/SoundWire/Samples/SdcaVad/Package/package.VcxProj b/audio/SoundWire/Samples/SdcaVad/Package/package.VcxProj new file mode 100644 index 00000000..3125e599 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/Package/package.VcxProj @@ -0,0 +1,166 @@ +<?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> + <ProjectReference Include="..\EventDetectorAdapter\EventDetectorContosoAdapter.vcxproj"> + <Project>{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}</Project> + </ProjectReference> + <ProjectReference Include="..\Apo\kws\KWSApo.vcxproj"> + <Project>{47358AD6-A48A-465B-965F-0A66F8BDFE23}</Project> + </ProjectReference> + <ProjectReference Include="..\SDCAVCodec\SDCAVCodec.vcxproj"> + <Project>{98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}</Project> + </ProjectReference> + <ProjectReference Include="..\SDCAVDsp\SDCAVDsp.vcxproj"> + <Project>{5FDD3888-48B5-496C-83B0-E107CFFF46BC}</Project> + </ProjectReference> + <ProjectReference Include="..\SDCAVXu\SDCAVXu.vcxproj"> + <Project>{B1B6FD46-A26E-4D07-BE2E-FD87725500DC}</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)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</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|ARM'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <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/SoundWire/Samples/SdcaVad/Package/package.VcxProj.Filters b/audio/SoundWire/Samples/SdcaVad/Package/package.VcxProj.Filters new file mode 100644 index 00000000..63b75548 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/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/SoundWire/Samples/SdcaVad/README.md b/audio/SoundWire/Samples/SdcaVad/README.md new file mode 100644 index 00000000..e440aadf --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/README.md @@ -0,0 +1,145 @@ +--- +page_type: sample +description: "The Microsoft SDCA Virtual Audio Device Driver (SdcaVad) shows how to develop ACX/SDCA audio drivers that expose support for SDCA audio devices." +languages: +- cpp +products: +- windows +- windows-wdk +urlFragment: sdcavad +--- + +# SDCA Virtual Audio Device Driver Sample + +## Introduction + +The Microsoft SDCA Virtual Audio Device Driver (SdcaVad) shows how to develop ACX/SDCA audio drivers that expose support for SDCA audio devices. + +The following table shows the features that are implemented in the various subdirectories of this sample. + +| Directory | Description | +| --- | --- | +| SdcaVCodec | SDCA Virual Codec Driver. | +| SdcaVDsp | SDCA Virual DSP Driver. | +| SdcaVXu | SDCA Virtual XU Driver. | +| Apo\kws | 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. | +| EventDetectorAdapter | Sample Event Detector Adapter. | + +## 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\sdcavad*). Double-click the *sdcavad* 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 six projects. + +### 2. Set the sample's configuration and platform + +In Solution Explorer, right-click **Solution 'sdcavad' (6 of 6 projects)**, and choose **Configuration Manager**. Make sure that the configuration and platform settings are the same for the six projects. Set the configuration to **Debug**, and the platform to **x64** 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\\sdcavad*, 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 set **Debug** and **x64**, then the built driver package will be saved to a folder named *Debug* inside a folder named *x64*. 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 | +| --- | --- | +| SdcaVCodec.sys | The SDCA Virtual Codec Driver file. | +| SdcaVCodec.inf | A information(INF) file that contians information needed to install the SDCA Virtual Codec Driver. | +| SdcaVDsp.sys | The SDCA Virtual DSP Driver file. | +| SdcaVDsp.inf | A information(INF) file that contians information needed to install the SDCA Virtual DSP Driver. | +| SdcaVXu.sys | The SDCA Virtual XU Driver file. | +| SdcaVXu.inf | A information(INF) file that contians information needed to install the SDCA Virtual XU Driver. | +| EventDetectorContosoAdapter.dll | Sample Event detector adapter. | +| SdcaVKwsApo.dll | The KWS APO. | +| SdcaVApo.inf | A information (INF) file that installs an APO device. | +| sdcavad.cat | A signed catalog file, which serves as the signature for the entire package. | + +## 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 SDCA sample 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, minimum version required for the WDK is 25926, which corresponds to the canary channel. + +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:\\SdcaVad*). Copy all the files from the built driver package on the host computer 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, but any user mode files (.dll files) will not be loaded. + +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. + +For more information on the subject, see [Driver signing](https://docs.microsoft.com/windows-hardware/drivers/install/driver-signing). + +### Install the driver + +#### Single INF files + +Each sample driver contains an INF file, which will install the sample driver. + +On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command: + +`devcon install SdcaVDsp.inf SOUNDWIRETEST\DSP` +`devcon install SdcaVCodec.inf Root\SDCAVCodec` + +Then, the XU INF (*SdcaVXu.inf*) and the APO INF (*SdcaVApo.inf*) can be installed - right-click the INF file and select **Install** to install it. + +After successfully installing the sample drivers, you're now ready to test it. + +### 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 *SDCA Virtual Dsp Audio Driver*. 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 *SDCA Virtual Codec Audio Driver*, 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 *SDCA Virtual Codec Audio Driver* driver. + +## HLK testing + +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. + +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 SdcaVad, 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. + +Besides, the current version of SdcaVad also failed the General Audio Test and the Device Power State Transition Test and we're investigating the failures. diff --git a/audio/SoundWire/Samples/SdcaVad/SDCAVad.sln b/audio/SoundWire/Samples/SdcaVad/SDCAVad.sln new file mode 100644 index 00000000..468a8e13 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SDCAVad.sln @@ -0,0 +1,185 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EventDetectorAdapter", "EventDetectorAdapter", "{A54839B3-5655-40FE-A908-3D4541341F3D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EventDetectorContosoAdapter", "EventDetectorAdapter\EventDetectorContosoAdapter.vcxproj", "{E0F02048-78A4-4FE8-B863-66E6CB6A2C37}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apo", "Apo", "{439D009C-33A7-49D5-991B-DC90856A4556}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KWSApo", "Apo\kws\KWSApo.vcxproj", "{47358AD6-A48A-465B-965F-0A66F8BDFE23}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{87A26F2D-E1DB-43B1-9DF8-84535829D72F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SdcaVCodec", "SdcaVCodec", "{604DD19C-D187-49E3-B99C-40EF15BE99AB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDCAVCodec", "SdcaVCodec\SDCAVCodec.vcxproj", "{98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SdcaVDsp", "SdcaVDsp", "{E9F3F705-E937-4B89-B23B-F0DC1AB32AE2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDCAVDsp", "SdcaVDsp\SDCAVDsp.vcxproj", "{5FDD3888-48B5-496C-83B0-E107CFFF46BC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SdcaVXu", "SdcaVXu", "{ECBA917D-ECAD-48BF-AA29-EEB0D1DA728F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDCAVXu", "SdcaVXu\SDCAVXu.vcxproj", "{B1B6FD46-A26E-4D07-BE2E-FD87725500DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|Win32 = Debug|Win32 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM.ActiveCfg = Debug|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM.Build.0 = Debug|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|ARM64.Build.0 = Debug|ARM64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.ActiveCfg = Debug|x64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|x64.Build.0 = Debug|x64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.ActiveCfg = Debug|Win32 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Debug|Win32.Build.0 = Debug|Win32 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM.ActiveCfg = Release|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM.Build.0 = Release|ARM + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.ActiveCfg = Release|ARM64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|ARM64.Build.0 = Release|ARM64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.ActiveCfg = Release|x64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|x64.Build.0 = Release|x64 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.ActiveCfg = Release|Win32 + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37}.Release|Win32.Build.0 = Release|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM.ActiveCfg = Debug|ARM + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM.Build.0 = Debug|ARM + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|ARM64.Build.0 = Debug|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.ActiveCfg = Debug|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|x64.Build.0 = Debug|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.ActiveCfg = Debug|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Debug|Win32.Build.0 = Debug|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM.ActiveCfg = Release|ARM + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM.Build.0 = Release|ARM + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.ActiveCfg = Release|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|ARM64.Build.0 = Release|ARM64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.ActiveCfg = Release|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|x64.Build.0 = Release|x64 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.ActiveCfg = Release|Win32 + {47358AD6-A48A-465B-965F-0A66F8BDFE23}.Release|Win32.Build.0 = Release|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.ActiveCfg = Debug|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.Build.0 = Debug|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM.Deploy.0 = Debug|ARM + {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|ARM64.Deploy.0 = Debug|ARM64 + {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}.Debug|x64.Deploy.0 = Debug|x64 + {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|Win32.Deploy.0 = Debug|Win32 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.ActiveCfg = Release|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.Build.0 = Release|ARM + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM.Deploy.0 = Release|ARM + {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|ARM64.Deploy.0 = Release|ARM64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Deploy.0 = Release|x64 + {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|Win32.Deploy.0 = Release|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM.ActiveCfg = Debug|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM.Build.0 = Debug|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM.Deploy.0 = Debug|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM64.Build.0 = Debug|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|x64.ActiveCfg = Debug|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|x64.Build.0 = Debug|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|x64.Deploy.0 = Debug|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|Win32.ActiveCfg = Debug|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|Win32.Build.0 = Debug|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Debug|Win32.Deploy.0 = Debug|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM.ActiveCfg = Release|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM.Build.0 = Release|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM.Deploy.0 = Release|ARM + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM64.ActiveCfg = Release|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM64.Build.0 = Release|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|ARM64.Deploy.0 = Release|ARM64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|x64.ActiveCfg = Release|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|x64.Build.0 = Release|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|x64.Deploy.0 = Release|x64 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|Win32.ActiveCfg = Release|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|Win32.Build.0 = Release|Win32 + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}.Release|Win32.Deploy.0 = Release|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM.ActiveCfg = Debug|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM.Build.0 = Debug|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM.Deploy.0 = Debug|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM64.Build.0 = Debug|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|x64.ActiveCfg = Debug|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|x64.Build.0 = Debug|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|x64.Deploy.0 = Debug|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|Win32.Build.0 = Debug|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Debug|Win32.Deploy.0 = Debug|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM.ActiveCfg = Release|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM.Build.0 = Release|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM.Deploy.0 = Release|ARM + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM64.ActiveCfg = Release|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM64.Build.0 = Release|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|ARM64.Deploy.0 = Release|ARM64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|x64.ActiveCfg = Release|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|x64.Build.0 = Release|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|x64.Deploy.0 = Release|x64 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|Win32.ActiveCfg = Release|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|Win32.Build.0 = Release|Win32 + {5FDD3888-48B5-496C-83B0-E107CFFF46BC}.Release|Win32.Deploy.0 = Release|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM.ActiveCfg = Debug|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM.Build.0 = Debug|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM.Deploy.0 = Debug|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM64.Build.0 = Debug|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|x64.ActiveCfg = Debug|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|x64.Build.0 = Debug|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|x64.Deploy.0 = Debug|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|Win32.Build.0 = Debug|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Debug|Win32.Deploy.0 = Debug|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM.ActiveCfg = Release|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM.Build.0 = Release|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM.Deploy.0 = Release|ARM + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM64.ActiveCfg = Release|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM64.Build.0 = Release|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|ARM64.Deploy.0 = Release|ARM64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|x64.ActiveCfg = Release|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|x64.Build.0 = Release|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|x64.Deploy.0 = Release|x64 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|Win32.ActiveCfg = Release|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|Win32.Build.0 = Release|Win32 + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC}.Release|Win32.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E0F02048-78A4-4FE8-B863-66E6CB6A2C37} = {A54839B3-5655-40FE-A908-3D4541341F3D} + {47358AD6-A48A-465B-965F-0A66F8BDFE23} = {439D009C-33A7-49D5-991B-DC90856A4556} + {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {87A26F2D-E1DB-43B1-9DF8-84535829D72F} + {98C9E1FB-3F06-4B5C-BA88-545AD0A80F94} = {604DD19C-D187-49E3-B99C-40EF15BE99AB} + {5FDD3888-48B5-496C-83B0-E107CFFF46BC} = {E9F3F705-E937-4B89-B23B-F0DC1AB32AE2} + {B1B6FD46-A26E-4D07-BE2E-FD87725500DC} = {ECBA917D-ECAD-48BF-AA29-EEB0D1DA728F} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {33CFA437-4CF0-4818-810F-4D78CF082C35} + EndGlobalSection +EndGlobal diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp new file mode 100644 index 00000000..e7b36b1f --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp @@ -0,0 +1,286 @@ +/*++ + + 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: + + CircuitHelper.cpp + +Abstract: + + This module contains helper functions for device.cpp and render.cpp files. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "CircuitHelper.h" + +#ifndef __INTELLISENSE__ +#include "CircuitHelper.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +) +{ + + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(CircuitInit, &CircuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(CircuitInit, AcxCircuitTypeRender); + + // + // Assign the circuit's pnp-power callbacks. + // + { + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecR_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecR_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(CircuitInit, &powerCallbacks); + } + + // + // Assign the circuit's composite callbacks. + // + { + ACX_CIRCUIT_COMPOSITE_CALLBACKS compositeCallbacks; + ACX_CIRCUIT_COMPOSITE_CALLBACKS_INIT(&compositeCallbacks); + compositeCallbacks.EvtAcxCircuitCompositeCircuitInitialize = CodecR_EvtCircuitCompositeCircuitInitialize; + compositeCallbacks.EvtAcxCircuitCompositeInitialize = CodecR_EvtCircuitCompositeInitialize; + AcxCircuitInitSetAcxCircuitCompositeCallbacks(CircuitInit, &compositeCallbacks); + } + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + CodecR_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + CircuitInit, + CodecR_EvtCircuitCreateStream)); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &CircuitInit, Circuit)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ULONG ElementCount, + _In_reads_(ElementCount) ACXELEMENT* Elements, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Explicitly connect the circuit/elements. Note that driver doens't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both render and capture devices. + // + // circuit.pin[default_sink] -> 1st element.pin[default_in] + // 1st element.pin[default_out] -> 2nd element.pin[default_in] + // 2nd element.pin[default_out] -> circuit.pin[default_source] + // + const int numElements = 2; + const int numConnections = numElements + 1; + + ACX_CONNECTION connections[numConnections]; + ACX_CONNECTION_INIT(&connections[0], Circuit, Elements[ElementCount - 2]); + ACX_CONNECTION_INIT(&connections[1], Elements[ElementCount - 2], Elements[ElementCount - 1]); + ACX_CONNECTION_INIT(&connections[2], Elements[ElementCount - 1], Circuit); + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections))); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ObjBagAddBlob( + _In_ ACXOBJECTBAG ObjBag, + _In_z_ const char* Blob +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(VendorPropertiesBlock); + STRING vendorBlob; + RtlInitString(&vendorBlob, Blob); + WDFMEMORY vendorBlobMem; + RETURN_NTSTATUS_IF_FAILED(WdfMemoryCreatePreallocated(NULL, vendorBlob.Buffer, vendorBlob.MaximumLength, &vendorBlobMem)); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddBlob(ObjBag, &VendorPropertiesBlock, vendorBlobMem)); + WdfObjectDelete(vendorBlobMem); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ObjBagAddEndpointId( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &EndpointId, Value)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ObjBagAddDataPortNumber( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DataPortNumber); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &DataPortNumber, Value)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ObjBagAddTestUI4( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &TestUI4, Value)); + + return status; +} + + +PAGED_CODE_SEG +NTSTATUS ObjBagAddCircuitId( + _In_ ACXOBJECTBAG ObjBag, + _In_ GUID Guid +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, CircuitId); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddGuid(ObjBag, &CircuitId, Guid)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ObjBagAddUnicodeStrings( + _In_ ACXOBJECTBAG ObjBag, + _In_ UNICODE_STRING FriendlyNameStr, + _In_ UNICODE_STRING NameStr +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(FriendlyName); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUnicodeString(ObjBag, &FriendlyName, &FriendlyNameStr)); + + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(Name); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUnicodeString(ObjBag, &Name, &NameStr)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS AddJack( + _In_ WDF_OBJECT_ATTRIBUTES Attributes, + _In_ ACXPIN Pin, + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + ACX_JACK_CONFIG jackCfg; + ACX_JACK_CONFIG_INIT(&jackCfg); + jackCfg.Description.ChannelMapping = ChannelMapping; + jackCfg.Description.Color = Color; + jackCfg.Description.ConnectionType = ConnectionType; + jackCfg.Description.GeoLocation = GeoLocation; + jackCfg.Description.GenLocation = GenLocation; + jackCfg.Description.PortConnection = PortConnection; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, CODEC_JACK_CONTEXT); + Attributes.ParentObject = Pin; + + ACXJACK jack; + RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(Pin, &Attributes, &jackCfg, &jack)); + + ASSERT(jack != NULL); + + PCODEC_JACK_CONTEXT jackCtx; + jackCtx = GetCodecJackContext(jack); + ASSERT(jackCtx); + jackCtx->Dummy = 0; + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(Pin, &jack, 1)); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h new file mode 100644 index 00000000..c3776c1c --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h @@ -0,0 +1,84 @@ +/*++ + + 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: + + CircuitHelper.h + +Abstract: + + This module contains helper functions for device.cpp and render.cpp files. + +Environment: + + Kernel mode + +--*/ + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ULONG ElementCount, + _In_reads_(ElementCount) ACXELEMENT* Elements, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddBlob( + _In_ ACXOBJECTBAG ObjBag, + _In_z_ const char* Blob +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddEndpointId( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddDataPortNumber( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddTestUI4( + _In_ ACXOBJECTBAG ObjBag, + _In_ UINT Value +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddCircuitId( + _In_ ACXOBJECTBAG ObjBag, + _In_ GUID Guid +); + +PAGED_CODE_SEG +NTSTATUS ObjBagAddUnicodeStrings( + _In_ ACXOBJECTBAG ObjBag, + _In_ UNICODE_STRING FriendlyNameStr, + _In_ UNICODE_STRING NameStr +); + +PAGED_CODE_SEG +NTSTATUS AddJack( + _In_ WDF_OBJECT_ATTRIBUTES Attributes, + _In_ ACXPIN Pin, + _In_ ULONG ChannelMapping, + _In_ ULONG Color, + _In_ ACX_JACK_CONNECTION_TYPE ConnectionType, + _In_ ACX_JACK_GEO_LOCATION GeoLocation, + _In_ ACX_JACK_GEN_LOCATION GenLocation, + _In_ ACX_JACK_PORT_CONNECTION PortConnection +); diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp new file mode 100644 index 00000000..d56a172b --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp @@ -0,0 +1,262 @@ +/*++ + + 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: + + Extension.cpp + +Abstract: + + SDCA XU functions + +Environment: + + Kernel mode + +--*/ + +#include "private.h" + +#ifndef __INTELLISENSE__ +#include "Extension.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetJackOverride +( + _In_ PVOID Context, // SDCA Context + _In_ BOOLEAN Override // TRUE: Override + // FALSE: Default SDCA behavior +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(Override); + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + + devCtx = GetCodecDeviceContext(Context); + ASSERT(devCtx != NULL); + + devCtx->SdcaXuData.bExtensionJackOVerride = Override; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetJackSelectedMode +( + _In_ PVOID Context, // SDCA Context + _In_ ULONG GroupEntityId, // SDCA Group Entity ID for Jack(s) + _In_ ULONG SelectedMode // Type of jack type overriden by XU +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(GroupEntityId); + UNREFERENCED_PARAMETER(SelectedMode); + NTSTATUS status = STATUS_SUCCESS; + + return status; +} + +#pragma code_seg() +NTSTATUS Codec_SdcaXuPDEPowerReferenceAcquire +( + _In_ PVOID Context, // SDCA Context + _In_ ULONG PowerDomainEntityId, // SDCA Entity ID for entity + _In_ SDCAXU_POWER_STATE RequiredState // Power state the PowerDomain needs to be in +) +{ + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(PowerDomainEntityId); + UNREFERENCED_PARAMETER(RequiredState); + NTSTATUS status = STATUS_SUCCESS; + + return status; +} + +#pragma code_seg() +NTSTATUS Codec_SdcaXuPDEPowerReferenceRelease +( + _In_ PVOID Context, // SDCA Context + _In_ ULONG PowerDomainEntityId, // SDCA Entity ID for entity + _In_ SDCAXU_POWER_STATE ReleasedState // Power state the PowerDomain no longer needs to be in +) +{ + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(PowerDomainEntityId); + UNREFERENCED_PARAMETER(ReleasedState); + NTSTATUS status = STATUS_SUCCESS; + + return status; +} + +#pragma code_seg() +NTSTATUS Codec_SdcaXuReadDeferredAudioControls +( + _In_ PVOID Context, // SDCA Context + _Inout_ PSDCA_AUDIO_CONTROLS Controls // Array of SDCA Audio Controls +) +{ + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(Controls); + NTSTATUS status = STATUS_SUCCESS; + + return status; +} + +#pragma code_seg() +NTSTATUS Codec_SdcaXuWriteDeferredAudioControls +( + _In_ PVOID Context, // SDCA Context + _Inout_ PSDCA_AUDIO_CONTROLS Controls // Array of SDCA Audio Controls +) +{ + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(Controls); + NTSTATUS status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetXUEntities +( + _In_ PVOID Context, + _In_ ULONG NumEntities, + _In_reads_(NumEntities) + ULONG EntityIDs[] + ) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext((WDFDEVICE)Context); + + if (NumEntities) + { + PULONG pXUEntities = (PULONG)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(ULONG) * NumEntities, DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == pXUEntities, STATUS_INSUFFICIENT_RESOURCES); + + for (ULONG i = 0; i < NumEntities; i++) + { + pXUEntities[i] = EntityIDs[i]; + } + + devCtx->SdcaXuData.numXUEntities = NumEntities; + devCtx->SdcaXuData.XUEntities = pXUEntities; + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuRegisterForInterrupts +( + _In_ PVOID Context, + _In_ PSDCAXU_INTERRUPT_INFO InterruptInfo +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext((WDFDEVICE)Context); + + RETURN_NTSTATUS_IF_TRUE(InterruptInfo->Size != sizeof(SDCAXU_INTERRUPT_INFO), STATUS_INVALID_PARAMETER_1); + + PSDCAXU_INTERRUPT_INFO pInterruptInfo = (PSDCAXU_INTERRUPT_INFO)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + InterruptInfo->Size, + DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == pInterruptInfo, STATUS_MEMORY_NOT_ALLOCATED); + + RtlCopyMemory(pInterruptInfo, InterruptInfo, InterruptInfo->Size); + + devCtx->SdcaXuData.InterruptInfo = pInterruptInfo; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS Codec_GetSdcaXu(_In_ WDFDEVICE Device) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + PCODEC_DEVICE_CONTEXT devCtx; + + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + RtlZeroMemory(&devCtx->SdcaXuData, sizeof(devCtx->SdcaXuData)); + + // Initialize Interface for requesting correct version + devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Size = sizeof(SDCAXU_INTERFACE_V0101); + devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Version = SDCAXU_INTERFACE_VERSION_0101; + + // + // Provide SDCA Interface that XU driver can call into + // XU driver will copy these function addresses while + // handling Query Interface + // + devCtx->SdcaXuData.ExtensionInterface.EvtSetXUEntities = Codec_SdcaXuSetXUEntities; + devCtx->SdcaXuData.ExtensionInterface.EvtRegisterForInterrupts = Codec_SdcaXuRegisterForInterrupts; + devCtx->SdcaXuData.ExtensionInterface.EvtSetJackOverride = Codec_SdcaXuSetJackOverride; + devCtx->SdcaXuData.ExtensionInterface.EvtSetJackSelectedMode = Codec_SdcaXuSetJackSelectedMode; + devCtx->SdcaXuData.ExtensionInterface.EvtPDEPowerReferenceAcquire = Codec_SdcaXuPDEPowerReferenceAcquire; + devCtx->SdcaXuData.ExtensionInterface.EvtPDEPowerReferenceRelease = Codec_SdcaXuPDEPowerReferenceRelease; + devCtx->SdcaXuData.ExtensionInterface.EvtReadDeferredAudioControls = Codec_SdcaXuReadDeferredAudioControls; + devCtx->SdcaXuData.ExtensionInterface.EvtWriteDeferredAudioControls = Codec_SdcaXuWriteDeferredAudioControls; + + status = WdfFdoQueryForInterface( + Device, + &SDCAXU_INTERFACE, + (PINTERFACE)&(devCtx->SdcaXuData.ExtensionInterface), + sizeof(SDCAXU_INTERFACE_V0101), + SDCAXU_INTERFACE_VERSION_0101, + Device + ); + + if (NT_SUCCESS(status)) + { + devCtx->SdcaXuData.bSdcaXu = TRUE; + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS Codec_SetSdcaXuHwConfig(_In_ WDFDEVICE Device) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVCodecLog); + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface; + PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context; + + SdcaXuAcpiBlob acpiBlob; + acpiBlob.NumEndpoints = 2; + RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetHwConfig(exContext, SdcaXuHwConfigTypeAcpiBlob, &acpiBlob, sizeof(acpiBlob))); + + return status; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj new file mode 100644 index 00000000..c855cfc0 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj @@ -0,0 +1,364 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <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|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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + <ACX_VERSION_MAJOR>1</ACX_VERSION_MAJOR> + <ACX_VERSION_MINOR>0</ACX_VERSION_MINOR> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppTraceFunction> + </WppTraceFunction> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inx)" Include="*.inx" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\inc\NewDelete.h" /> + <ClInclude Include="CircuitHelper.h" /> + <ClInclude Include="private.h" /> + <ClInclude Include="streamengine.h" /> + <ClInclude Include="Trace.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="capture.cpp" /> + <ClCompile Include="CircuitHelper.cpp" /> + <ClCompile Include="device.cpp" /> + <ClCompile Include="driver.cpp" /> + <ClCompile Include="Extension.cpp" /> + <ClCompile Include="..\common\NewDelete.cpp" /> + <ClCompile Include="render.cpp" /> + <ClCompile Include="streamengine.cpp" /> + <ResourceCompile Include="resources.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters new file mode 100644 index 00000000..44bc3f92 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.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"> + <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> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx new file mode 100644 index 00000000..88c9eba4 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx @@ -0,0 +1,146 @@ +;/*++ +; +;Copyright (c) Microsoft Corporation. All rights reserved. +; +;Module Name: +; +; SDCAVCodec.INF +; +;--*/ + +[Version] +Signature="$WINDOWS NT$" +Class=SYSTEM +ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} +Provider=%ProviderName% +DriverVer=06/13/2016, 1.0.0.1 +CatalogFile=SDCAVad.cat +PnpLockdown=1 + +[DestinationDirs] +DefaultDestDir = 13 + +;***************************************** +; Audio Device Install Section +;***************************************** +[Manufacturer] +%StdMfg%=Standard,NT$ARCH$.10.0...19041 + +[Standard.NT$ARCH$.10.0...19041] +%WdfCodecDevice.DeviceDesc%=Audio_Device, ROOT\SDCAVCodec + +[Audio_Device.NT] +CopyFiles=Audio_Device.NT.Copy + +[Audio_Device.NT.Copy] +SDCAVCodec.sys + + +[Audio_Device.NT.HW] +AddReg=FilterLevelReg + +;**************************************************** +; SDCAXu filters are installed in filter level +; SDCAXu +;**************************************************** +[FilterLevelReg] +HKR,,LowerFilterLevels,%REG_MULTI_SZ%,"SDCAXu","DefaultLowerFilter" +HKR,,LowerFilterDefaultLevel,,"DefaultLowerFilter" + +;-------------- Service installation + +[Audio_Device.NT.Services] +AddService = SDCAVCodec, %SPSVCINST_ASSOCSERVICE%, Audio_Service_Inst + +[Audio_Service_Inst] +DisplayName = %WdfCodecDevice.DeviceDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %13%\SDCAVCodec.sys + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +SDCAVCodec.sys = 1,, + + +[Audio_Device.NT.Wdf] +KmdfService = SDCAVCodec, Audio_wdfsect +[Audio_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + +; +; render interfaces: speaker +; +[Audio_Device.I.Speaker] +AddReg=Audio_Device.I.Speaker.AddReg +[Audio_Device.I.Speaker.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%Audio_Device.Speaker.szPname% +; The following lines opt-in to pull mode. +HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY% +HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1 + +; +; capture interfaces: microphone +; +[Audio_Device.I.Microphone] +AddReg=Audio_Device.I.Microphone.AddReg +[Audio_Device.I.Microphone.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%Audio_Device.Microphone.szPname% +; The following lines opt-in to pull mode. +HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY% +HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1 + +; +; PnP add interface directives for static enumerated audio endpoints. +; +[Audio_Device.NT.Interfaces] +; Interfaces for render endpoint. +AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Speaker%, Audio_Device.I.Speaker +AddInterface=%KSCATEGORY_TOPOLOGY%, %KSNAME_Speaker%, Audio_Device.I.Speaker + +; Interfaces for mic capture endpoint +AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Microphone%, Audio_Device.I.Microphone +AddInterface=%KSCATEGORY_TOPOLOGY%, %KSNAME_Microphone%, Audio_Device.I.Microphone + +[Strings] +; +;Non-localizable +; +KSNAME_Speaker="Speaker0" +KSNAME_Microphone="Microphone0" + +SPSVCINST_ASSOCSERVICE = 0x00000002 +ProviderName = "VS_Microsoft" + +Proxy.CLSID = "{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO = "{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER = "{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_REALTIME = "{EB115FFC-10C8-4964-831D-6DCB02E6F23F}" +KSCATEGORY_TOPOLOGY = "{DDA54A40-1E4C-11D1-A050-405705C10000}" + +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +KSNODETYPE_ANY = "{00000000-0000-0000-0000-000000000000}" + +PKEY_AudioEndpoint_ControlPanelPageProvider = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},1" +PKEY_AudioEndpoint_Association = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},2" +PKEY_AudioEndpoint_Supports_EventDriven_Mode = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},7" +PKEY_AudioEndpoint_Default_VolumeInDb = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},9" +REG_MULTI_SZ = 0x00010000 +; +;Localizable +; +StdMfg = "SDCA Virtual Codec Audio Device" +DiskId1 = "SDCA Virtual Codec Audio Driver Installation Disk" +WdfCodecDevice.DeviceDesc = "SDCA Virtual Codec Audio Driver" + +;; friendly names +Audio_Device.Speaker.szPname="SDCA Virtual Codec Speaker" +Audio_Device.Microphone.szPname="SDCA Virtual Codec Microphone" + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h new file mode 100644 index 00000000..4b292930 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + +Trace.h + +--*/ + +#pragma once + +#include <WppRecorder.h> +#include <evntrace.h> // For TRACE_LEVEL definitions + +#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) +#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4) + +// {C456FD64-2AC1-4A72-8280-B4163555CD03} +#define WPP_CONTROL_GUIDS \ +WPP_DEFINE_CONTROL_GUID(DrvLogger,(c456fd64,2ac1,4a72,8280,b4163555cd03), \ + WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \ + ) + +#include "trace_macros.h" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp new file mode 100644 index 00000000..df6de34c --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp @@ -0,0 +1,1150 @@ +/*++ + + 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: + + Capture.cpp + +Abstract: + + Contains ACX Capture factory and circuit + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "soundwirecontroller.h" +#include "sdcastreaming.h" +#include "CircuitHelper.h" + +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "capture.tmh" +#endif + +ACX_PROPERTY_ITEM KwsProperties[] = +{ + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_DEVICE_CAPABILITY, + ACX_PROPERTY_ITEM_FLAG_GET, + &CodecC_EvtCircuitDeviceKwsCapability, // Event to call + NULL, // Reserved + 0, // ControlCb + sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR) // ValueCb + }, + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_VAD_CAPABILITY, + ACX_PROPERTY_ITEM_FLAG_GET, + &CodecC_EvtCircuitVadCapability, // Event to call + NULL, // Reserved + 0, // ControlCb + sizeof(VAD_DESCRIPTOR) // ValueCb + }, + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_VAD_ENTITIES, + ACX_PROPERTY_ITEM_FLAG_GET, + &CodecC_EvtCircuitVadEntities, // Event to call + NULL, // Reserved + 0, // ControlCb + sizeof(VAD_ENTITIES) // ValueCb + }, + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_ACCESS_EVENTS, + ACX_PROPERTY_ITEM_FLAG_SET, + &CodecC_EvtCircuitSetKwsAccessEvents, // Event to call + NULL, // Reserved + 0, // ControlCb + sizeof(SDCA_KWS_NOTIFICATIONS) // ValueCb + }, + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_CONFIGURE_VAD_PORT, + ACX_PROPERTY_ITEM_FLAG_SET, + &CodecC_EvtCircuitConfigureVadPort, // Event to call + NULL, // Reserved + 0, // ControlCb + sizeof(SDCA_KWS_PREPARE_PARAMS) // ValueCb + }, + { + &KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_CLEANUP_VAD_PORT, + ACX_PROPERTY_ITEM_FLAG_SET, + &CodecC_EvtCircuitCleanupVadPort, // Event to call + // No parameters - can only have one + }, +}; + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitVadCapability( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; + PVAD_DESCRIPTOR value; + ULONG valueCb; + ULONG_PTR minSize; + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + ULONG formatCount = 0; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet); + + value = (PVAD_DESCRIPTOR)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + // + // Compute min size. + // + minSize = sizeof(VAD_DESCRIPTOR); + + // + // Sample only supports 1 format + // + formatCount = 1; + + // Note the VAD_DESCRIPTOR already has room for 1, hence subtracting that here + minSize += (formatCount - ANYSIZE_ARRAY) * sizeof(WAVEFORMATEXTENSIBLE); + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + } + else if (valueCb < minSize) + { + outDataCb = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + // + // Reset buffer. + // + RtlZeroMemory(value, valueCb); + + // It's safe for us to use the KwsDataFormat directly in AcxDataFormatGetWaveFormatExtensible + // because we control it and know it will have a proper WAVEFORMATEXTENSIBLE value. + RtlCopyMemory(value->Format, AcxDataFormatGetWaveFormatExtensible(circuitCtx->KwsDataFormat), sizeof(WAVEFORMATEXTENSIBLE)); + + value->FormatCount = formatCount; + + // + // All done. + // + outDataCb = minSize; + status = STATUS_SUCCESS; + } + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitVadEntities( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; + PVAD_DESCRIPTOR value; + ULONG valueCb; + ULONG_PTR minSize; + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet); + + value = (PVAD_DESCRIPTOR)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + // we're going to return 0 entities, so only the base structure + // is needed. + minSize = sizeof(VAD_ENTITIES); + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + } + else if (valueCb < minSize) + { + outDataCb = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + // + // Reset buffer. + // + RtlZeroMemory(value, valueCb); + + // we do not have disco info for this sample driver, so + // we have no entities to copy, but an empty list is sufficient + // for testing. + + outDataCb = minSize; + status = STATUS_SUCCESS; + } + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitDeviceKwsCapability( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; + PDEVICE_KWS_CAPABILITY_DESCRIPTOR value; + ULONG valueCb; + ULONG_PTR minSize; + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet); + + value = (PDEVICE_KWS_CAPABILITY_DESCRIPTOR)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + // + // Compute min size. + // + + minSize = sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR); + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + } + else if (valueCb < minSize) + { + outDataCb = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + // + // Reset buffer. + // + RtlZeroMemory(value, valueCb); + + // Get the Device KWS Capabilities + // In this sample, just return that Buffered is supported + value->DataPathsSupported = SupportedDataPathsBufferedRaw; + + // + // All done. + // + outDataCb = minSize; + status = STATUS_SUCCESS; + } + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitSetKwsAccessEvents( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; // default no size info + PSDCA_KWS_NOTIFICATIONS value; + ULONG valueCb; + ULONG minSize; + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet); + + minSize = sizeof(SDCA_KWS_NOTIFICATIONS); + + value = (PSDCA_KWS_NOTIFICATIONS)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + goto exit; + } + + if (valueCb < minSize) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + circuitCtx->KwsSuspendEvent = value->Suspend; + circuitCtx->KwsResumeEvent = value->Resume; + + status = STATUS_SUCCESS; + +exit: + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitConfigureVadPort( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; // default no size info + PSDCA_KWS_PREPARE_PARAMS value; + ULONG valueCb; + ULONG minSize; + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet); + + if (circuitCtx->KwsActiveVadStream) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + minSize = sizeof(SDCA_KWS_PREPARE_PARAMS); + + value = (PSDCA_KWS_PREPARE_PARAMS)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + goto exit; + } + + if (valueCb < minSize) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + if (value->DetectionFormat.Format.cbSize > sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + // Set up the hardware for KWS + circuitCtx->KwsActiveVadStream = TRUE; + status = STATUS_SUCCESS; + +exit: + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitCleanupVadPort( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; // default no size info + PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx; + + PAGED_CODE(); + + circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeProperty); + ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet); + + if (!circuitCtx->KwsActiveVadStream) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + // Deconfigure hardware + circuitCtx->KwsActiveVadStream = FALSE; + status = STATUS_SUCCESS; + +exit: + + WdfRequestCompleteWithInformation(Request, status, outDataCb); +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +#pragma code_seg() +VOID +CodecC_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +VOID +CodecC_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} + +PAGED_CODE_SEG +VOID +CodecC_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddCaptures( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Driver); + + PAGED_CODE(); + + // + // Add a static capture device. + // + RETURN_NTSTATUS_IF_FAILED(CodecC_AddStaticCapture(Device)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_DEVICE_CONTEXT); + PCODEC_CAPTURE_DEVICE_CONTEXT captureDevCtx; + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&captureDevCtx)); + + ASSERT(captureDevCtx); + + // + // Create a capture circuit associated with this device. + // + ACXCIRCUIT captureCircuit = NULL; + RETURN_NTSTATUS_IF_FAILED(CodecC_CreateCaptureCircuit(Device, &captureCircuit)); + + RETURN_NTSTATUS_IF_FAILED(Codec_SdcaXuSetCaptureEndpointConfig(Device, captureCircuit)); + + devCtx->Capture = captureCircuit; + + return status; +} + +EXTERN_C const GUID DECLSPEC_SELECTANY CODEC_CIRCUIT_CAPTURE_GUID; +EXTERN_C const GUID DECLSPEC_SELECTANY EXTENSION_CIRCUIT_CAPTURE_GUID; +EXTERN_C const GUID DECLSPEC_SELECTANY SYSTEM_CONTAINER_GUID; + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetCaptureEndpointConfig( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + DECLARE_CONST_UNICODE_STRING(circuitName, L"ExtensionMicrophone0"); + DECLARE_CONST_UNICODE_STRING(circuitUri, EXT_CAPTURE_CIRCUIT_URI); + +#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit") + PSDCAXU_ACX_CIRCUIT_CONFIG exCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength, + DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == exCircuitConfig, STATUS_INSUFFICIENT_RESOURCES); + auto exConfigFree = scope_exit([&exCircuitConfig]() { + ExFreePoolWithTag(exCircuitConfig, DRIVER_TAG); + }); + + // + // Provide circuit configuration to SDCA XU driver + // SDCA XU driver will generate circuits to match this configuration + // + if (devCtx->SdcaXuData.bSdcaXu) + { + exCircuitConfig->cbSize = sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength; + + exCircuitConfig->CircuitName = circuitName; + exCircuitConfig->CircuitName.Buffer = (PWCH)(exCircuitConfig + 1); + RtlCopyMemory(exCircuitConfig->CircuitName.Buffer, circuitName.Buffer, circuitName.MaximumLength); + + exCircuitConfig->CircuitContext = Circuit; + exCircuitConfig->CircuitType = AcxCircuitTypeCapture; + exCircuitConfig->ContainerID = SYSTEM_CONTAINER_GUID; + exCircuitConfig->ComponentID = EXTENSION_CIRCUIT_CAPTURE_GUID; + exCircuitConfig->ComponentUri = circuitUri; + + PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface; + PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context; + + RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetEndpointConfig(exContext, SdcaXuEndpointConfigTypeAcxCircuitConfig, exCircuitConfig, exCircuitConfig->cbSize)); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT * Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC capture circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Init output value. + // + *Circuit = NULL; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + + // + // Get a CircuitInit structure. + // + PACXCIRCUIT_INIT circuitInit = NULL; + circuitInit = AcxCircuitInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_NO_MEMORY); + auto circuitInitScope = scope_exit([&circuitInit]() { + AcxCircuitInitFree(circuitInit); + }); + + // + // Add circuit identifiers. + // + AcxCircuitInitSetComponentId(circuitInit, &CODEC_CIRCUIT_CAPTURE_GUID); + + DECLARE_CONST_UNICODE_STRING(circuitUri, CAPTURE_CIRCUIT_URI); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &circuitUri)); + + DECLARE_CONST_UNICODE_STRING(circuitName, L"Microphone0"); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(circuitInit, &circuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeCapture); + + // + // Assign the circuit's pnp-power callbacks. + // + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = CodecC_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = CodecC_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + circuitInit, + CodecC_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + circuitInit, + CodecC_EvtCircuitCreateStream)); + + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit, + KwsProperties, + ARRAYSIZE(KwsProperties))); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_CIRCUIT_CONTEXT); + ACXCIRCUIT circuit; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + circuitInitScope.release(); + + ASSERT(circuit != NULL); + CODEC_CAPTURE_CIRCUIT_CONTEXT *circuitCtx; + circuitCtx = GetCaptureCircuitContext(circuit); + ASSERT(circuitCtx); + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Add two custom circuit elements. Note that driver doesn't need to + // perform this step if it doesn't want to expose any circuit elements. + // + + // + // Create 1st custom circuit-element. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + const int numElements = 2; + ACXELEMENT elements[numElements] = {0}; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + CODEC_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetCodecElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom circuit-element. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetCodecElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add the circuit elements + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + + /////////////////////////////////////////////////////////// + // Create Capture Pin, using default pin id. + // Acx Circuit will create other pin by default. + // + // Allocate the formats this circuit supports. Use formats without + // channel mask for capture. + // + // PCM:44100 channel:2 24in32 + ACX_DATAFORMAT_CONFIG formatCfg; + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm44100c2_24in32_nomask); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT); + attributes.ParentObject = circuit; + + ACXDATAFORMAT formatPcm44100c2_24in32nomask; + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm44100c2_24in32nomask)); + + CODEC_FORMAT_CONTEXT *formatCtx; + formatCtx = GetCodecFormatContext(formatPcm44100c2_24in32nomask); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + // PCM:48000 channel:2 24in32 + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm48000c2_24in32_nomask); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT); + attributes.ParentObject = circuit; + + ACXDATAFORMAT formatPcm48000c2_24in32nomask; + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm48000c2_24in32nomask)); + + formatCtx = GetCodecFormatContext(formatPcm48000c2_24in32nomask); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + // This is the format we'll report support for with KWS. Note that DSP uses 4ch; that includes + // 2ch from the hardware + 2ch reference + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm16000c2nomask); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT); + attributes.ParentObject = circuit; + + ACXDATAFORMAT formatPcm16000c2nomask; + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm16000c2nomask)); + + formatCtx = GetCodecFormatContext(formatPcm16000c2nomask); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + /////////////////////////////////////////////////////////// + // + // Create Capture Pin. AcxCircuit creates the other pin by default. + // + + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecC_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG pinCfg; + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecC_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + ACXPIN pin; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + CODEC_PIN_CONTEXT *pinCtx; + pinCtx = GetCodecPinContext(pin); + ASSERT(pinCtx); + UNREFERENCED_PARAMETER(pinCtx); + + // + // Add our supported formats to the Default mode for the circuit + // + ACXDATAFORMATLIST formatList; + formatList = AcxPinGetRawDataFormatList(pin); + RETURN_NTSTATUS_IF_TRUE(NULL == formatList, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32nomask)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2_24in32nomask)); + + circuitCtx->KwsDataFormat = formatPcm16000c2nomask; + + // Add Capture Pin, using default pin id. + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create Bridge Pin. + // + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_MICROPHONE; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + + RETURN_NTSTATUS_IF_FAILED(AddJack(attributes, pin, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, RGB(0, 0, 0), AcxConnTypeAtapiInternal, AcxGeoLocFront, AcxGenLocPrimaryBox, AcxPortConnIntegratedDevice)); + + // Add capture bridge pin + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + + + // + // Explicitly connect the circuit/elements. Note that driver doens't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending on the + // source circuit pin on both render and capture devices. + // + // circuit.pin[default_sink] -> 1st element.pin[default_in] + // 1st element.pin[default_out] -> 2nd element.pin[default_in] + // 2nd element.pin[default_out] -> circuit.pin[default_source] + // + const int numConnections = numElements + 1; + ACX_CONNECTION connections[numConnections]; + ACX_CONNECTION_INIT(&connections[0], circuit, elements[0]); + ACX_CONNECTION_INIT(&connections[1], elements[0], elements[1]); + ACX_CONNECTION_INIT(&connections[2], elements[1], circuit); + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(circuit, connections, SIZEOF_ARRAY(connections))); + + // + // Set output value. + // + *Circuit = circuit; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtCircuitPowerUp( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtCircuitPowerDown( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CodecC_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + PCODEC_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + if (VarArguments) + { + // Get the variable arguments parameter and retrive the values set by the DSP object. + ULONG ui4Value = 0; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveUI4(VarArguments, &TestUI4, &ui4Value)); + + RETURN_NTSTATUS_IF_TRUE(ui4Value == 0, STATUS_UNSUCCESSFUL); + + ui4Value++; + + // Add the modified value back to object bag. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(VarArguments, &TestUI4, ui4Value)); + } + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + CodecC_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = Codec_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = Codec_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = Codec_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = Codec_EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_STREAM_CONTEXT); + attributes.EvtDestroyCallback = Codec_EvtStreamDestroy; + ACXSTREAM stream; + RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + CCaptureStreamEngine *streamEngine = NULL; + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CCaptureStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES); + + CODEC_STREAM_CONTEXT *streamCtx; + streamCtx = GetCodecStreamContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)streamEngine; + streamEngine = NULL; + + // + // Post stream creation initialization. + // + + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXELEMENT elements[2] = {0}; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + CODEC_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetCodecElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetCodecElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp new file mode 100644 index 00000000..e4805669 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp @@ -0,0 +1,808 @@ +/*++ + + 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: + + Device.cpp + +Abstract: + + Plug and Play module. This file contains routines to handle pnp requests. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "CircuitHelper.h" + +#ifndef __INTELLISENSE__ +#include "device.tmh" +#endif + +UNICODE_STRING g_RegistryPath = {0}; // This is used to store the registry settings path for the driver + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +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 + +--*/ + +{ + PAGED_CODE(); + + // 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, DRIVER_TAG); + + if (g_RegistryPath.Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // ExAllocatePool2 zeros memory. + + RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtBusDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. All the software resources + should be allocated in this callback. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = Codec_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = Codec_EvtDeviceReleaseHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + // + // Specify the type of context needed. + // Use default locking, i.e., none. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = Codec_EvtDeviceContextCleanup; + + // + // Create the device. + // + WDFDEVICE device = NULL; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device)); + + // + // Init Codec's device context. + // + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != NULL); + devCtx->Render = NULL; + devCtx->Capture = NULL; + + // + // Assume XU lower filter driver is not present + // + devCtx->SdcaXuData.bSdcaXu = FALSE; + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + // + // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so + // that you don't get the popup in usermode (on Win2K) when you surprise + // remove the device. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.SurpriseRemovalOK = WdfTrue; + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + + // + // Get SDCA XU filter interface + // + RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(Codec_GetSdcaXu(device), STATUS_NOT_SUPPORTED); + + if (devCtx->SdcaXuData.bSdcaXu) + { + RETURN_NTSTATUS_IF_FAILED(Codec_SetSdcaXuHwConfig(device)); + } + + RETURN_NTSTATUS_IF_FAILED(Codec_AddRenderComposites(device)); + + RETURN_NTSTATUS_IF_FAILED(Codec_AddCaptureComposites(device)); + + // + // Add a render device and a capture device. + // + RETURN_NTSTATUS_IF_FAILED(CodecR_AddRenders(Driver, device)); + + // + // Add a render device and a capture device. + // + RETURN_NTSTATUS_IF_FAILED(CodecC_AddCaptures(Driver, device)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + + RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device)); + + // + // Add static circuit to device's list. + // + ASSERT(devCtx->Render); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Render)); + + ASSERT(devCtx->Capture); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Capture)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVCodecLog); + + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + + // + // Init the idle policy structure. + // + //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = 10000; // 10-sec + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceAssignS0IdleSettings(Device, &idleSettings)); + + return status; +} + +#pragma code_seg() + +DEFINE_GUID(CODEC_CIRCUIT_RENDER_GUID, +0xfd4b6e78, 0x51e0, 0x4aa6, 0x90, 0x98, 0xbb, 0xcb, 0x70, 0x89, 0xcb, 0x6a); + +DEFINE_GUID(EXTENSION_CIRCUIT_RENDER_GUID, +0x656ab905, 0x55fb, 0x4b08, 0xb6, 0x01, 0xd7, 0xf0, 0xc1, 0xce, 0x36, 0x2c); + +// {17F5B19F-C2C7-4B53-AFB9-49A0283D0DCE} +DEFINE_GUID(DSP_CIRCUIT_SPEAKER_GUID, + 0x17f5b19f, 0xc2c7, 0x4b53, 0xaf, 0xb9, 0x49, 0xa0, 0x28, 0x3d, 0xd, 0xce); + +DEFINE_GUID(CODEC_CIRCUIT_CAPTURE_GUID, +0x67ec5936, 0xa395, 0x4e93, 0xbe, 0x8a, 0xfc, 0xed, 0xe3, 0x1b, 0xad, 0x40); + +DEFINE_GUID(EXTENSION_CIRCUIT_CAPTURE_GUID, +0x44c69385, 0xa012, 0x405f, 0x8a, 0x9a, 0x7b, 0x44, 0x29, 0x71, 0xc8, 0x50); + +// {6F9EACF7-CD2D-4030-9E49-7CC4ADEFF192} +DEFINE_GUID(DSP_CIRCUIT_MICROPHONE_GUID, + 0x6f9eacf7, 0xcd2d, 0x4030, 0x9e, 0x49, 0x7c, 0xc4, 0xad, 0xef, 0xf1, 0x92); + +DEFINE_GUID(SYSTEM_CONTAINER_GUID, +0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + + +#define DSP_FACTORY_URI L"acpi:obj-path:\\_SB.PC00.HDAS" + +#define RENDER_CIRCUIT_UNIQUE_ID L"{613fd364-64bb-4b69-99bc-5b075ea9756b}" +#define RENDER_CIRCUIT_FRIENDLY_NAME L"Speaker-360" +#define RENDER_CIRCUIT_NAME L"Speaker" +#define CAPTURE_CIRCUIT_UNIQUE_ID L"{3A509246-5902-4AA2-9E06-C7C8D10461C3}" +#define CAPTURE_CIRCUIT_FRIENDLY_NAME L"Microphone-360" +#define CAPTURE_CIRCUIT_NAME L"Microphone" + +#define CIRCUIT_RENDER_VENDOR_BLOB "Streaming_Speaker" +#define CIRCUIT_CAPTURE_VENDOR_BLOB "Streaming_MicrophoneArray" + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddRenderComposites(_In_ WDFDEVICE Device) +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(Codec_AddComposites(Device, CompositeType_RENDER)); + + return status; +} + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddCaptureComposites(_In_ WDFDEVICE Device) +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(Codec_AddComposites(Device, CompositeType_CAPTURE)); + + return status; +} + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVCodecLog); + + UNICODE_STRING circuit_IDs[] = { + { sizeof(RENDER_CIRCUIT_UNIQUE_ID) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_UNIQUE_ID), RENDER_CIRCUIT_UNIQUE_ID }, + { sizeof(CAPTURE_CIRCUIT_UNIQUE_ID) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_UNIQUE_ID), CAPTURE_CIRCUIT_UNIQUE_ID} + }; + + UNICODE_STRING circuit_friendly_names[] = { + { sizeof(RENDER_CIRCUIT_FRIENDLY_NAME) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_FRIENDLY_NAME), RENDER_CIRCUIT_FRIENDLY_NAME }, + { sizeof(CAPTURE_CIRCUIT_FRIENDLY_NAME) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_FRIENDLY_NAME), CAPTURE_CIRCUIT_FRIENDLY_NAME} + }; + + UNICODE_STRING circuit_names[] = { + { sizeof(RENDER_CIRCUIT_NAME) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_NAME), RENDER_CIRCUIT_NAME }, + { sizeof(CAPTURE_CIRCUIT_NAME) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_NAME), CAPTURE_CIRCUIT_NAME} + }; + + UNICODE_STRING codec_circuit_uris[] = { + { sizeof(RENDER_CIRCUIT_URI) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_URI), RENDER_CIRCUIT_URI }, + { sizeof(CAPTURE_CIRCUIT_URI) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_URI), CAPTURE_CIRCUIT_URI} + }; + + UNICODE_STRING extension_circuit_uris[] = { + { sizeof(EXT_RENDER_CIRCUIT_URI) - sizeof(WCHAR), sizeof(EXT_RENDER_CIRCUIT_URI), EXT_RENDER_CIRCUIT_URI }, + { sizeof(EXT_CAPTURE_CIRCUIT_URI) - sizeof(WCHAR), sizeof(EXT_CAPTURE_CIRCUIT_URI), EXT_CAPTURE_CIRCUIT_URI} + }; + + GUID dsp_circuit_guids[] = { + DSP_CIRCUIT_SPEAKER_GUID, + DSP_CIRCUIT_MICROPHONE_GUID + }; + + UNICODE_STRING dsp_factory_uris[] = { + { sizeof(DSP_FACTORY_URI) - sizeof(WCHAR), sizeof(DSP_FACTORY_URI), DSP_FACTORY_URI }, + { sizeof(DSP_FACTORY_URI) - sizeof(WCHAR), sizeof(DSP_FACTORY_URI), DSP_FACTORY_URI} + }; + + const char* dsp_factory_vendor_blobs[] = { + CIRCUIT_RENDER_VENDOR_BLOB, + CIRCUIT_CAPTURE_VENDOR_BLOB + }; + + PCODEC_DEVICE_CONTEXT deviceCtx = NULL; + deviceCtx = GetCodecDeviceContext(Device); + ASSERT(deviceCtx); + + // + // May be called again for rebalance + // Add composites only once + // + RETURN_NTSTATUS_IF_TRUE(0 != deviceCtx->refComposite[compositeType], STATUS_SUCCESS); + + // + // Object bag + // + // This obj-bag config setting is shared by all composite/circuit templates. + ACX_OBJECTBAG_CONFIG objBagCfg; + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = AcxGetManager(NULL); + + ACXOBJECTBAG objBag = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + auto objBag_scope = scope_exit([&objBag]() { + if (objBag != NULL) + { + WdfObjectDelete(objBag); + } + }); + + // + // Add a test unsigned int 4 bytes to the object bag + // + RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 0)); + + // + // Add unique circuit ID to the object bag + // This unique Id will be picked up by DSP circuit + // + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID); + GUID uniqueID = { 0 }; + RETURN_NTSTATUS_IF_FAILED(RtlGUIDFromString(&circuit_IDs[compositeType], &uniqueID)); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddGuid(objBag, &UniqueID, uniqueID)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddUnicodeStrings(objBag, circuit_friendly_names[compositeType], circuit_names[compositeType])); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddEndpointId(objBag, 9)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddDataPortNumber(objBag, 9)); + + // + // Composite template. + // + ULONG circuitsInTemplate = 0; + ACXCIRCUITTEMPLATE circuits[3] = { 0 }; + ACX_COMPOSITE_TEMPLATE_CONFIG compositeCfg; + ACX_COMPOSITE_TEMPLATE_CONFIG_INIT(&compositeCfg); + compositeCfg.Properties = objBag; + compositeCfg.Flags |= AcxCompositeTemplateConfigSingleton; + + ACXCOMPOSITETEMPLATE composite = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxCompositeTemplateCreate(WdfGetDriver(), + &attributes, + &compositeCfg, + &composite)); + + auto composite_scope = scope_exit([&composite]() { + WdfObjectDelete(composite); + composite = NULL; + }); + + objBag = NULL; + + // This attribute setting is shared by all the circuit templates. + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = composite; + + // Codec template. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 2)); + + ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg1; + ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg1); + circuitCfg1.CircuitProperties = objBag; + circuitCfg1.CircuitUri = &codec_circuit_uris[compositeType]; + + ULONG codecIndex = circuitsInTemplate; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(), + &attributes, + &circuitCfg1, + &circuits[circuitsInTemplate++])); + + objBag = NULL; + + // XU template. + // + // Check if XU is present + // and compose with Xu circuit + // + if (deviceCtx->SdcaXuData.bSdcaXu) + { + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 2)); + + ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg2; + ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg2); + circuitCfg2.CircuitProperties = objBag; + circuitCfg2.CircuitUri = &extension_circuit_uris[compositeType]; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(), + &attributes, + &circuitCfg2, + &circuits[circuitsInTemplate++])); + + objBag = NULL; + } + + // Dsp template. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 3)); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddCircuitId(objBag, dsp_circuit_guids[compositeType])); + + RETURN_NTSTATUS_IF_FAILED(ObjBagAddBlob(objBag, dsp_factory_vendor_blobs[compositeType])); + + ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg3; + ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg3); + circuitCfg3.CircuitProperties = objBag; + circuitCfg3.FactoryUri = &dsp_factory_uris[compositeType]; + circuitCfg3.Flags |= AcxCircuitTemplateCircuitOnDemand; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(), + &attributes, + &circuitCfg3, + &circuits[circuitsInTemplate++])); + + objBag = NULL; + objBag_scope.release(); + + RETURN_NTSTATUS_IF_FAILED(AcxCompositeTemplateAssignCircuits(composite, circuits, circuitsInTemplate)); + + // Select the core circuit. + AcxCompositeTemplateSetCoreCircuit(composite, circuits[codecIndex]); + + // Final step. + RETURN_NTSTATUS_IF_FAILED(AcxManagerAddCompositeTemplate(AcxGetManager(NULL), composite)); + + deviceCtx->Composite[compositeType] = composite; + composite_scope.release(); + + deviceCtx->refComposite[compositeType]++; + + return status; +} + +#pragma code_seg() +NTSTATUS +Codec_RemoveComposites(_In_ WDFDEVICE Device) +{ + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT deviceCtx = NULL; + deviceCtx = GetCodecDeviceContext(Device); + ASSERT(deviceCtx); + + for (ULONG compositeType = CompositeType_RENDER; compositeType <= CompositeType_CAPTURE; ) + { + if (deviceCtx->refComposite[compositeType]) + { + deviceCtx->refComposite[compositeType]--; + if (deviceCtx->refComposite[compositeType] == 0) + { + if (deviceCtx->Composite[compositeType] != NULL) + { + RETURN_NTSTATUS_IF_FAILED(AcxManagerRemoveCompositeTemplate(AcxGetManager(NULL), deviceCtx->Composite[compositeType])); + + WdfObjectDelete(deviceCtx->Composite[compositeType]); + deviceCtx->Composite[compositeType] = NULL; + } + } + } + + compositeType++; + } + + return status; +} + +#pragma code_seg() +VOID +Codec_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice + ) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + WDFDEVICE device; + PCODEC_DEVICE_CONTEXT devCtx; + + + device = (WDFDEVICE)WdfDevice; + devCtx = GetCodecDeviceContext(device); + ASSERT(devCtx != NULL); + + Codec_RemoveComposites(device); + + if (devCtx->SdcaXuData.XUEntities) + { + ExFreePoolWithTag(devCtx->SdcaXuData.XUEntities, DRIVER_TAG); + devCtx->SdcaXuData.numXUEntities = 0; + } + if (devCtx->SdcaXuData.InterruptInfo) + { + ExFreePoolWithTag(devCtx->SdcaXuData.InterruptInfo, DRIVER_TAG); + devCtx->SdcaXuData.InterruptInfo = NULL; + } +} + +#pragma code_seg() +VOID +Codec_EvtStreamDestroy( + _In_ WDFOBJECT Object + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + ctx = GetCodecStreamContext((ACXSTREAM)Object); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + ctx->StreamEngine = NULL; + delete streamEngine; +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay +) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->GetHWLatency(FifoSize, Delay); +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->PrepareHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->ReleaseHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamRun( + _In_ ACXSTREAM Stream + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Run(); +} + + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamPause( + _In_ ACXSTREAM Stream + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Pause(); +} + +PAGED_CODE_SEG +NTSTATUS +Codec_EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ) +{ + PCODEC_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetCodecStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AssignDrmContentId(DrmContentId, DrmRights); +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp new file mode 100644 index 00000000..4c9f937e --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp @@ -0,0 +1,218 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Driver.cpp + +Abstract: + + Sample soundwire Codec driver + +Environment: + + Kernel mode only + +--*/ + +#include "private.h" + +#ifndef __INTELLISENSE__ +#include "driver.tmh" +#endif + +RECORDER_LOG g_SDCAVCodecLog{ nullptr }; + +INIT_CODE_SEG +void +Test_ClientVersionHigherThanFramework() +{ + PAGED_CODE(); + + // example on how to check if a function is available. + /* + if (ACX_IS_FUNCTION_AVAILABLE(AcxCircuitCreate)) { + DbgPrint("Available: AcxCircuitCreate\n"); + } + else + { + DbgPrint("Not available: AcxCircuitCreate\n"); + ASSERT(FALSE); + } + */ + + if (ACX_IS_FIELD_AVAILABLE(ACX_DEVICEINIT_CONFIG, SynchronizationScope)) { + ACX_DEVICEINIT_CONFIG config; + ACX_DEVICEINIT_CONFIG_INIT(&config); + DbgPrint("Available: ACX_DEVICEINIT_CONFIG.SynchronizationScope\n"); + } + else + { + DbgPrint("Not available: ACX_DEVICEINIT_CONFIG.SynchronizationScope\n"); + ASSERT(FALSE); + } +} + +PAGED_CODE_SEG +VOID Codec_DriverUnload(_In_ WDFDRIVER Driver) +{ + PAGED_CODE(); + + if (!Driver) + { + ASSERT(FALSE); + return; + } + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); + + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + return; +} + +INIT_CODE_SEG +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WPP_INIT_TRACING(DriverObject, RegistryPath); + + auto exit = scope_exit([&status, &DriverObject]() { + if (!NT_SUCCESS(status)) + { + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + WPP_CLEANUP(DriverObject); + } + else + { + DrvLogInfo(g_SDCAVCodecLog, FLAG_INIT, "ACX SDCA Virtual Codec Driver Init complete, %!STATUS!", status); + } + }); + + RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath)); + + // + // Initiialize 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, + // you can override that by manually setting the EvtDriverUnload in the + // config structure. In general xxx_CONFIG_INIT macros are provided to + // initialize most commonly used members. + // + + WDF_DRIVER_CONFIG wdfCfg; + WDF_DRIVER_CONFIG_INIT(&wdfCfg, Codec_EvtBusDeviceAdd); + wdfCfg.EvtDriverUnload = Codec_DriverUnload; + + // + // Add a driver context. (for illustration purposes only). + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DRIVER_CONTEXT); + + // + // Create a framework driver object to represent our driver. + // + WDFDRIVER driver; + RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, // Driver Attributes + &wdfCfg, // Driver Config Info + &driver // hDriver + )); + + RECORDER_CONFIGURE_PARAMS recorderConfig; + RECORDER_CONFIGURE_PARAMS_INIT(&recorderConfig); + recorderConfig.CreateDefaultLog = FALSE; + WppRecorderConfigure(&recorderConfig); + + RECORDER_LOG_CREATE_PARAMS recorderLogCreateParams; + RECORDER_LOG_CREATE_PARAMS_INIT(&recorderLogCreateParams, NULL); + recorderLogCreateParams.TotalBufferSize = WPP_TOTAL_BUFFER_SIZE; + recorderLogCreateParams.ErrorPartitionSize = WPP_ERROR_PARTITION_SIZE; + + RtlStringCbPrintfA(recorderLogCreateParams.LogIdentifier, + RECORDER_LOG_IDENTIFIER_MAX_CHARS, + "SDCAVCodec"); + + RECORDER_LOG logHandle = NULL; + status = WppRecorderLogCreate(&recorderLogCreateParams, &logHandle); + if (!NT_SUCCESS(status)) + { + logHandle = NULL; + + // Non fatal failure + status = STATUS_SUCCESS; + } + + g_SDCAVCodecLog = logHandle; + + // + // Post init. + // + ACX_DRIVER_CONFIG acxCfg; + ACX_DRIVER_CONFIG_INIT(&acxCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg)); + + // + // Test ACX bindings. + // + ACX_DRIVER_VERSION_AVAILABLE_PARAMS ver; + ACX_DRIVER_VERSION_AVAILABLE_PARAMS_INIT(&ver, 1, 0); + if (!AcxDriverIsVersionAvailable(driver, &ver)) { + status = STATUS_DRIVER_INTERNAL_ERROR; + DbgPrint("Unexpected ACX library version.\n"); + ASSERT(FALSE); + } + RETURN_NTSTATUS_IF_FAILED(status); + + Test_ClientVersionHigherThanFramework(); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h new file mode 100644 index 00000000..602133ba --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h @@ -0,0 +1,522 @@ +/*++ + +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: + + private.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#ifndef _PRIVATE_H_ +#define _PRIVATE_H_ + +#include "cpp_utils.h" + +#include "NewDelete.h" + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#pragma warning(disable:4200) // +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int + +#include <initguid.h> +#include <ntddk.h> +#include <ntstrsafe.h> +#include <ntintsafe.h> + +#pragma warning(default:4200) +#pragma warning(default:4201) +#pragma warning(default:4214) + +#include <wdf.h> +#include <acx.h> + +#include "SoundWireController.h" +#include "SdcaXu.h" + +#include "trace.h" + +#include <TestProperties.h> + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +extern RECORDER_LOG g_SDCAVCodecLog; + +// Simple ACX driver +#define DRIVER_TAG (ULONG) 'Ccds' + +// Number of millisecs per sec. +#define MS_PER_SEC 1000 + +// Number of hundred nanosecs per sec. +#define HNS_PER_SEC 10000000 + +// Compatible ID for render/capture +#define ACX_CODEC_TEST_COMPATIBLE_ID L"{99a0ee05-7167-4b63-843d-19d6d285942e}" + +// Container ID for render/capture +#define ACX_CODEC_TEST_CONTAINER_ID L"{00000000-0000-0000-ffff-ffffffffffff}" + +#define RENDER_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\RENDER" +#define EXT_RENDER_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\RENDER_xu" +#define CAPTURE_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\CAPTURE" +#define EXT_CAPTURE_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\CAPTURE_xu" + +#undef MIN +#undef MAX +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef SIZEOF_ARRAY +#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) +#endif // !defined(SIZEOF_ARRAY) + +#ifndef RGB +#define RGB(r, g, b) (DWORD)(r << 16 | g << 8 | b) +#endif + + +// +// Example Acpi blob for Hardware configuration +// +typedef struct _SdcaXuAcpiBlob +{ + // Number of endpoints + ULONG NumEndpoints; + +}SdcaXuAcpiBlob, *PSdcaXuAcpiBlob; + +#define ALL_CHANNELS_ID UINT32_MAX +#define MAX_CHANNELS 2 + +// +// Ks support. +// +#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \ + KSPROPERTY_TYPE_GET | \ + KSPROPERTY_TYPE_SET + +// +// Define CODEC driver context. +// +typedef struct _CODEC_DRIVER_CONTEXT { + ULONG reserved; +} CODEC_DRIVER_CONTEXT, *PCODEC_DRIVER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DRIVER_CONTEXT, GetCodecDriverContext) + +// +// Extension Unit specific data +// +typedef struct _SDCAXU_DATA +{ + BOOLEAN bSdcaXu; + BOOLEAN bExtensionJackOVerride; + SDCAXU_INTERFACE_V0101 ExtensionInterface; + ULONG numXUEntities; + ULONG *XUEntities; + PSDCAXU_INTERRUPT_INFO InterruptInfo; +}SDCAXU_DATA, *PSDCAXU_DATA; + +// +// Define CODEC device context. +// +typedef struct _CODEC_DEVICE_CONTEXT { + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + ACXCOMPOSITETEMPLATE Composite[2]; + ULONG refComposite[2]; + SDCAXU_DATA SdcaXuData; + +} CODEC_DEVICE_CONTEXT, *PCODEC_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DEVICE_CONTEXT, GetCodecDeviceContext) + +// +// Define RENDER device context. +// +typedef struct _CODEC_RENDER_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} CODEC_RENDER_DEVICE_CONTEXT, *PCODEC_RENDER_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_DEVICE_CONTEXT, GetRenderDeviceContext) + +// +// Define RENDER circuit context. +// +typedef struct _CODEC_RENDER_CIRCUIT_CONTEXT { + ACXMUTE MuteElement; + ACXVOLUME VolumeElement; +} CODEC_RENDER_CIRCUIT_CONTEXT, *PCODEC_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_CIRCUIT_CONTEXT, GetRenderCircuitContext) + +// +// Define CAPTURE device context. +// +typedef struct _CODEC_CAPTURE_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} CODEC_CAPTURE_DEVICE_CONTEXT, *PCODEC_CAPTURE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext) + +// +// Define CAPTURE circuit context. +// +typedef struct _CODEC_CAPTURE_CIRCUIT_CONTEXT { + BOOLEAN KwsActiveVadStream; + KEVENT KwsSuspendEvent; + KEVENT KwsResumeEvent; + ACXDATAFORMAT KwsDataFormat; +} CODEC_CAPTURE_CIRCUIT_CONTEXT, *PCODEC_CAPTURE_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_CIRCUIT_CONTEXT, GetCaptureCircuitContext) + +// +// Define CODEC render/capture stream context. +// +typedef struct _CODEC_STREAM_CONTEXT { + PVOID StreamEngine; +} CODEC_STREAM_CONTEXT, *PCODEC_STREAM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_STREAM_CONTEXT, GetCodecStreamContext) + +// +// Define CODEC circuit/stream element context. +// +typedef struct _CODEC_ELEMENT_CONTEXT { + BOOLEAN Dummy; +} CODEC_ELEMENT_CONTEXT, *PCODEC_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_ELEMENT_CONTEXT, GetCodecElementContext) + +// +// Define CODEC circuit/stream element context. +// +typedef struct _CODEC_MUTE_ELEMENT_CONTEXT { + BOOL MuteState[MAX_CHANNELS]; + WDFTIMER Timer; // for testing only. +} CODEC_MUTE_ELEMENT_CONTEXT, *PCODEC_MUTE_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_MUTE_ELEMENT_CONTEXT, GetCodecMuteElementContext) + +// +// Define CODEC mute timer context. +// +typedef struct _CODEC_MUTE_TIMER_CONTEXT { + ACXMUTE MuteElement; +} CODEC_MUTE_TIMER_CONTEXT, *PCODEC_MUTE_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_MUTE_TIMER_CONTEXT, GetCodecMuteTimerContext) + +// +// Define CODEC circuit/stream element context. +// +typedef struct _CODEC_VOLUME_ELEMENT_CONTEXT { + LONG VolumeLevel[MAX_CHANNELS]; + WDFTIMER Timer; // for testing only. +} CODEC_VOLUME_ELEMENT_CONTEXT, *PCODEC_VOLUME_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_VOLUME_ELEMENT_CONTEXT, GetCodecVolumeElementContext) + + +#define VOLUME_STEPPING 0x8000 +#define VOLUME_LEVEL_MAXIMUM 0x00000000 +#define VOLUME_LEVEL_MINIMUM (-96 * 0x10000) + +// +// Define CODEC mute timer context. +// +typedef struct _CODEC_VOLUME_TIMER_CONTEXT { + ACXVOLUME VolumeElement; +} CODEC_VOLUME_TIMER_CONTEXT, *PCODEC_VOLUME_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_VOLUME_TIMER_CONTEXT, GetCodecVolumeTimerContext) + + +// +// Define CODEC format context. +// +typedef struct _CODEC_FORMAT_CONTEXT { + BOOLEAN Dummy; +} CODEC_FORMAT_CONTEXT, *PCODEC_FORMAT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_FORMAT_CONTEXT, GetCodecFormatContext) + +typedef struct _CODEC_PIN_CONTEXT { + BOOLEAN Dummy; +} CODEC_PIN_CONTEXT, *PCODEC_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_PIN_CONTEXT, GetCodecPinContext) + +typedef struct _CODEC_JACK_CONTEXT +{ + ULONG Dummy; +} CODEC_JACK_CONTEXT, *PCODEC_JACK_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_JACK_CONTEXT, GetCodecJackContext) + +typedef enum { + CompositeType_RENDER, + CompositeType_CAPTURE +}CompositeType; + +// +// Driver prototypes. +// +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD Codec_DriverUnload; +EVT_WDF_DRIVER_DEVICE_ADD Codec_EvtBusDeviceAdd; + +// Device callbacks. + +EVT_WDF_DEVICE_PREPARE_HARDWARE Codec_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Codec_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Codec_EvtDeviceContextCleanup; + +// Stream callbacks shared between Capture and Render + +EVT_WDF_OBJECT_CONTEXT_DESTROY Codec_EvtStreamDestroy; +EVT_ACX_STREAM_GET_HW_LATENCY Codec_EvtStreamGetHwLatency; +EVT_ACX_STREAM_PREPARE_HARDWARE Codec_EvtStreamPrepareHardware; +EVT_ACX_STREAM_RELEASE_HARDWARE Codec_EvtStreamReleaseHardware; +EVT_ACX_STREAM_RUN Codec_EvtStreamRun; +EVT_ACX_STREAM_PAUSE Codec_EvtStreamPause; +EVT_ACX_STREAM_ASSIGN_DRM_CONTENT_ID Codec_EvtStreamAssignDrmContentId; + +// Render callbacks. + +EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecR_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM CodecR_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecR_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecR_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET CodecR_EvtStreamSetRenderPacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecR_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecR_EvtPinContextCleanup; + +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE CodecR_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE CodecR_EvtCircuitCompositeInitialize; + +// Capture callbacks. + +EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecC_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM CodecC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP CodecC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN CodecC_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT CodecC_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecC_EvtPinContextCleanup; + +EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecC_EvtStreamRequestPreprocess; + +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitDeviceKwsCapability; +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitVadCapability; +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitVadEntities; +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitSetKwsAccessEvents; +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitConfigureVadPort; +EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitCleanupVadPort; + +EVT_ACX_MUTE_ASSIGN_STATE CodecR_EvtMuteAssignStateCallback; +EVT_ACX_MUTE_RETRIEVE_STATE CodecR_EvtMuteRetrieveStateCallback; +EVT_WDF_TIMER CodecR_EvtMuteTimerFunc; +EVT_ACX_VOLUME_ASSIGN_LEVEL CodecR_EvtVolumeAssignLevelCallback; +EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecR_EvtVolumeRetrieveLevelCallback; +EVT_WDF_TIMER CodecR_EvtVolumeTimerFunc; +EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecR_EvtStreamRequestPreprocess; + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +// +// Used to store the registry settings path for the driver +// +extern UNICODE_STRING g_RegistryPath; + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath + ); + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType); + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddRenderComposites(_In_ WDFDEVICE Device); + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +Codec_AddCaptureComposites(_In_ WDFDEVICE Device); + +#pragma code_seg() +NTSTATUS +Codec_RemoveComposites(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS +Codec_SetPowerPolicy( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddRenders( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT * Circuit + ); + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddCaptures( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +CodecC_AddStaticCapture( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +CodecC_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT * Circuit + ); + +// +// Extension Unit +// +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetJackOverride +( + _In_ PVOID Context, // SDCA Context + _In_ BOOLEAN Override // TRUE: Override + // FALSE: Default SDCA behavior +); + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetJackSelectedMode +( + _In_ PVOID Context, // SDCA Context + _In_ ULONG GroupEntityId, // SDCA Group Entity ID for Jack(s) + _In_ ULONG SelectedMode // Type of jack type overriden by XU +); + +#pragma code_seg() +NTSTATUS Codec_SdcaXuPDEPowerReferenceAcquire +( + _In_ PVOID Context, + _In_ ULONG PowerDomainEntityId, + _In_ SDCAXU_POWER_STATE RequiredState +); + +#pragma code_seg() +NTSTATUS Codec_SdcaXuPDEPowerReferenceRelease +( + _In_ PVOID Context, + _In_ ULONG PowerDomainEntityId, + _In_ SDCAXU_POWER_STATE ReleasedState +); + +#pragma code_seg() +NTSTATUS Codec_SdcaXuReadDeferredAudioControls +( + _In_ PVOID Context, + _Inout_ PSDCA_AUDIO_CONTROLS Controls +); + +#pragma code_seg() +NTSTATUS Codec_SdcaXuWriteDeferredAudioControls +( + _In_ PVOID Context, + _Inout_ PSDCA_AUDIO_CONTROLS Controls +); + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetXUEntities +( + _In_ PVOID Context, + _In_ ULONG NumEntities, + _In_reads_(NumEntities) + ULONG EntityIDs[] +); + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuRegisterForInterrupts +( + _In_ PVOID Context, + _In_ PSDCAXU_INTERRUPT_INFO InterruptInfo +); + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetRenderEndpointConfig +( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetCaptureEndpointConfig +( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS Codec_GetSdcaXu(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS Codec_SetSdcaXuHwConfig(_In_ WDFDEVICE Device); + +#pragma code_seg() + +#endif // _PRIVATE_H_ diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp new file mode 100644 index 00000000..901398dc --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp @@ -0,0 +1,1310 @@ +/*++ + + 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: + + Render.cpp + +Abstract: + + Contains ACX Capture factory and circuit + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "soundwirecontroller.h" +#include "sdcastreaming.h" +#include "CircuitHelper.h" + +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "render.tmh" +#endif + +//#define CODEC_NEXT_CIRCUIT_STR L"\\??\\ROOT#AcxAmpTestDriver#0000#{2c6bb644-e1ae-47f8-9a2b-1d1fa750f2fa}\\Speaker0" +//#define CODEC_NEXT_CIRCUIT_STR L"\\??\\ROOT#AcxAmpTestDriver#0000#{6994AD04-93EF-11D0-A3CC-00A0C9223196}\\Speaker0" + +//#define CODEC_PREVIOUS_CIRCUIT_STR L"\\??\\AcxDspTestDriver#DynamicEnumSpeaker0#1&6244bc4&d&00#{2c6bb644-e1ae-47f8-9a2b-1d1fa750f2fa}\\Speaker0" +//#define CODEC_PREVIOUS_CIRCUIT_STR L"\\??\\AcxDspTestDriver#DynamicEnumSpeaker0#1&6244bc4&0&00#{6994AD04-93EF-11D0-A3CC-00A0C9223196}\\Speaker0" + +PAGED_CODE_SEG +VOID +CodecR_EvtPinCInstancesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPinCTypesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPinDataFlowCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPinDataRangesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPinDataIntersectionCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtAcxPinSetDataFormat ( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtMuteAssignStateCallback( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _In_ ULONG State + ) +{ + PAGED_CODE(); + + ASSERT(Mute); + PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(Mute); + ASSERT(muteCtx); + + if (Channel != ALL_CHANNELS_ID) + { + muteCtx->MuteState[Channel] = State; + } + else + { + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + muteCtx->MuteState[i] = State; + } + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +NTAPI +CodecR_EvtMuteRetrieveStateCallback( + _In_ ACXMUTE Mute, + _In_ ULONG Channel, + _Out_ ULONG *State + ) +{ + PAGED_CODE(); + + ASSERT(Mute); + PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(Mute); + ASSERT(muteCtx); + + if (Channel == ALL_CHANNELS_ID) + { + Channel = 0; + } + + *State = muteCtx->MuteState[Channel]; + + return STATUS_SUCCESS; +} + +// +// Testing mute element. +// +#pragma code_seg() +VOID +CodecR_EvtMuteTimerFunc( + _In_ WDFTIMER Timer + ) +{ + PCODEC_MUTE_TIMER_CONTEXT timerCtx = GetCodecMuteTimerContext(Timer); + + ASSERT(timerCtx != NULL); + ASSERT(timerCtx->MuteElement != NULL); + + PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(timerCtx->MuteElement); + ASSERT(muteCtx != NULL); + + // update settings 0 <-> 1 + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + muteCtx->MuteState[i] = !muteCtx->MuteState[i]; + } + + AcxMuteChangeStateNotification(timerCtx->MuteElement); +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtVolumeAssignLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _In_ LONG VolumeLevel + ) +{ + PAGED_CODE(); + + ASSERT(Volume); + PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +NTAPI +CodecR_EvtVolumeRetrieveLevelCallback( + _In_ ACXVOLUME Volume, + _In_ ULONG Channel, + _Out_ LONG *VolumeLevel + ) +{ + PAGED_CODE(); + + ASSERT(Volume); + PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel == ALL_CHANNELS_ID) + { + Channel = 0; + } + + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + + return STATUS_SUCCESS; +} + +// +// Testing volume element. +// +#pragma code_seg() +VOID +CodecR_EvtVolumeTimerFunc( + _In_ WDFTIMER Timer + ) +{ + PCODEC_VOLUME_TIMER_CONTEXT timerCtx = GetCodecVolumeTimerContext(Timer); + + ASSERT(timerCtx != NULL); + ASSERT(timerCtx->VolumeElement != NULL); + + PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(timerCtx->VolumeElement); + ASSERT(volumeCtx != NULL); + + // Toggle volume between max and min + for (ULONG i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = volumeCtx->VolumeLevel[i] == VOLUME_LEVEL_MAXIMUM ? VOLUME_LEVEL_MINIMUM : VOLUME_LEVEL_MAXIMUM; + } + + AcxVolumeChangeLevelNotification(timerCtx->VolumeElement); +} + +#pragma code_seg() +VOID +CodecR_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin + ) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddRenders( + _In_ WDFDRIVER Driver, + _In_ WDFDEVICE Device + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Add a static render device. + // + status = CodecR_AddStaticRender(Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_AddStaticRender( + _In_ WDFDEVICE Device +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + // + // Alloc audio context to current device. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_DEVICE_CONTEXT); + PCODEC_RENDER_DEVICE_CONTEXT renderDevCtx; + RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&renderDevCtx)); + ASSERT(renderDevCtx); + + // + // Create a render circuit associated with this device. + // + ACXCIRCUIT renderCircuit = NULL; + RETURN_NTSTATUS_IF_FAILED(CodecR_CreateRenderCircuit(Device, &renderCircuit)); + + RETURN_NTSTATUS_IF_FAILED(Codec_SdcaXuSetRenderEndpointConfig(Device, renderCircuit)); + + devCtx->Render = renderCircuit; + + return status; +} + +EXTERN_C const GUID DECLSPEC_SELECTANY CODEC_CIRCUIT_RENDER_GUID; +EXTERN_C const GUID DECLSPEC_SELECTANY EXTENSION_CIRCUIT_RENDER_GUID; +EXTERN_C const GUID DECLSPEC_SELECTANY SYSTEM_CONTAINER_GUID; + +PAGED_CODE_SEG +NTSTATUS Codec_SdcaXuSetRenderEndpointConfig +( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVCodecLog); + + NTSTATUS status = STATUS_SUCCESS; + + PCODEC_DEVICE_CONTEXT devCtx; + devCtx = GetCodecDeviceContext(Device); + ASSERT(devCtx != NULL); + + DECLARE_CONST_UNICODE_STRING(circuitName, L"ExtensionSpeaker0"); + DECLARE_CONST_UNICODE_STRING(circuitUri, EXT_RENDER_CIRCUIT_URI); + +#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit") + PSDCAXU_ACX_CIRCUIT_CONFIG exCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength, + DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == exCircuitConfig, STATUS_INSUFFICIENT_RESOURCES); + auto exConfigFree = scope_exit([&exCircuitConfig]() { + ExFreePoolWithTag(exCircuitConfig, DRIVER_TAG); + }); + + // + // Provide circuit configuration to SDCA XU driver + // SDCA XU driver will generate circuits to match this configuration + // + if (devCtx->SdcaXuData.bSdcaXu) + { + exCircuitConfig->cbSize = sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength; + + exCircuitConfig->CircuitName = circuitName; + exCircuitConfig->CircuitName.Buffer = (PWCH)(exCircuitConfig + 1); + RtlCopyMemory(exCircuitConfig->CircuitName.Buffer, circuitName.Buffer, circuitName.MaximumLength); + + exCircuitConfig->CircuitContext = Circuit; + exCircuitConfig->CircuitType = AcxCircuitTypeRender; + exCircuitConfig->ContainerID = SYSTEM_CONTAINER_GUID; + exCircuitConfig->ComponentID = EXTENSION_CIRCUIT_RENDER_GUID; + exCircuitConfig->ComponentUri = circuitUri; + + PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface; + PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context; + + RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetEndpointConfig(exContext, SdcaXuEndpointConfigTypeAcxCircuitConfig, exCircuitConfig, exCircuitConfig->cbSize)); + } + + return status; +} + +// {3CE41646-9BF2-4A9E-B851-D711CAE9AEA8} +DEFINE_GUID(SDCAVADPropsetId, + 0x3ce41646, 0x9bf2, 0x4a9e, 0xb8, 0x51, 0xd7, 0x11, 0xca, 0xe9, 0xae, 0xa8); + +typedef enum { + SDCAVAD_PROPERTY_TEST1, + SDCAVAD_PROPERTY_TEST2, + SDCAVAD_PROPERTY_TEST3, + SDCAVAD_PROPERTY_TEST4, + SDCAVAD_PROPERTY_TEST5, + SDCAVAD_PROPERTY_TEST6, +} SDCAVAD_Properties; + +PAGED_CODE_SEG +NTSTATUS +CodecR_SDCAVADPropertyTest1( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(pValue); + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST1"); + + *ValueCbOut = 0; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_SDCAVADPropertyTest2( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST2"); + + *((PULONG)pValue) = 10; + *ValueCbOut = sizeof(ULONG); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_SDCAVADPropertyTest5( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(pValue); + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST5"); + + *ValueCbOut = 0; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_SDCAVADPropertyTest6( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST6"); + + *((PULONG)pValue) = 12; + *ValueCbOut = sizeof(ULONG); + + return status; +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPropertyCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Object); + + ACX_REQUEST_PARAMETERS params; + ACX_REQUEST_PARAMETERS_INIT(¶ms); + + AcxRequestGetParameters(Request, ¶ms); + + NTSTATUS status = STATUS_SUCCESS; + PVOID Value = params.Parameters.Property.Value; + ULONG ValueCb = params.Parameters.Property.ValueCb; + ULONG ValueCbOut = 0; + + switch (params.Parameters.Property.Id) + { + case SDCAVAD_PROPERTY_TEST1: + status = CodecR_SDCAVADPropertyTest1(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST2: + status = CodecR_SDCAVADPropertyTest2(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST5: + status = CodecR_SDCAVADPropertyTest5(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST6: + status = CodecR_SDCAVADPropertyTest6(Value, ValueCb, &ValueCbOut); + break; + default: + break; + } + + WdfRequestCompleteWithInformation(Request, status, ValueCbOut); +} + +PAGED_CODE_SEG +VOID +CodecR_EvtPropertyVendorSpecificCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Object); + + ACX_REQUEST_PARAMETERS params; + ACX_REQUEST_PARAMETERS_INIT(¶ms); + + AcxRequestGetParameters(Request, ¶ms); + + NTSTATUS status = STATUS_SUCCESS; + + // The Class Driver will send IOCTL_SOUNDWIRE_VENDOR_SPECIFIC with Control/Value to the SoundWire Controller. + + PVIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL control = (PVIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL)params.Parameters.Property.Control; + ULONG controlCb = params.Parameters.Property.ControlCb; + + PVIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA value = (PVIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA)params.Parameters.Property.Value; + ULONG valueCb = params.Parameters.Property.ValueCb; + + ULONG_PTR information = 0; + + // Validate we have enough control data + if (controlCb < sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL)) + { + status = STATUS_INVALID_PARAMETER; + } + else if (control->VendorSpecificSize != sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL)) + { + status = STATUS_INVALID_PARAMETER; + } + else if (control->VendorSpecificId == VirtualStackVendorSpecificRequestGetTestData) + { + if (valueCb == 0 && value == nullptr) + { + status = STATUS_BUFFER_OVERFLOW; + information = sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA); + } + else if (valueCb < sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA)) + { + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + value->Test1 = 0x12345678; + value->Test2 = 0x87654321; + information = sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA); + } + } + else if (control->VendorSpecificId == VirtualStackVendorSpecificRequestSetTestConfig) + { + DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: VENDOR SPECIFIC Set Test Config %d", control->Config.IsScatterGather); + } + else + { + status = STATUS_INVALID_PARAMETER; + } + + WdfRequestCompleteWithInformation(Request, status, information); +} + +static ACX_PROPERTY_ITEM g_CircuitProperties[] = +{ + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST1, + ACX_PROPERTY_ITEM_FLAG_SET, + CodecR_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST2, + ACX_PROPERTY_ITEM_FLAG_GET, + CodecR_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST5, + ACX_PROPERTY_ITEM_FLAG_SET, + CodecR_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST6, + ACX_PROPERTY_ITEM_FLAG_GET, + CodecR_EvtPropertyCallback + }, + { + &KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_VENDOR_SPECIFIC, + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_SET, + CodecR_EvtPropertyVendorSpecificCallback + }, +}; + +PAGED_CODE_SEG +NTSTATUS +CodecR_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT * Circuit +) +/*++ + +Routine Description: + + This routine builds the CODEC render circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVCodecLog); + + // + // Get a CircuitInit structure. + // + PACXCIRCUIT_INIT circuitInit = NULL; + circuitInit = AcxCircuitInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_NO_MEMORY); + auto circuitInitScope = scope_exit([&circuitInit]() { + AcxCircuitInitFree(circuitInit); + }); + + // + // Init output value. + // + *Circuit = NULL; + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + + // + // Add circuit identifiers. + // + AcxCircuitInitSetComponentId(circuitInit, &CODEC_CIRCUIT_RENDER_GUID); + + DECLARE_CONST_UNICODE_STRING(circuitUri, RENDER_CIRCUIT_URI); + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &circuitUri)); + + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT); + DECLARE_CONST_UNICODE_STRING(circuitName, L"Speaker0"); + + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit, + g_CircuitProperties, + SIZEOF_ARRAY(g_CircuitProperties))); + + + RETURN_NTSTATUS_IF_FAILED(CreateRenderCircuit(circuitInit, circuitName, Device, &circuit)); + circuitInitScope.release(); + + CODEC_RENDER_CIRCUIT_CONTEXT *circuitCtx; + ASSERT(circuit != NULL); + circuitCtx = GetRenderCircuitContext(circuit); + ASSERT(circuitCtx); + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Add two custom circuit elements. Note that driver doesn't need to + // perform this step if it doesn't want to expose any circuit elements. + // + + // + // Create 1st custom circuit-element (mute element). + // + ACX_MUTE_CALLBACKS muteCallbacks; + ACX_MUTE_CALLBACKS_INIT(&muteCallbacks); + muteCallbacks.EvtAcxMuteAssignState = CodecR_EvtMuteAssignStateCallback; + muteCallbacks.EvtAcxMuteRetrieveState = CodecR_EvtMuteRetrieveStateCallback; + + ACX_MUTE_CONFIG muteCfg; + ACX_MUTE_CONFIG_INIT(&muteCfg); + muteCfg.ChannelsCount = MAX_CHANNELS; + muteCfg.Callbacks = &muteCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_MUTE_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + const int numElements = 2; + ACXELEMENT elements[numElements] = {0}; + RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(circuit, &attributes, &muteCfg, (ACXMUTE *)&elements[0])); + + ASSERT(elements[0] != NULL); + CODEC_MUTE_ELEMENT_CONTEXT *muteCtx; + muteCtx = GetCodecMuteElementContext(elements[0]); + ASSERT(muteCtx); + UNREFERENCED_PARAMETER(muteCtx); + + circuitCtx->MuteElement = (ACXMUTE)elements[0]; + + // + // Testing async mute state change. + // + { + WDF_TIMER_CONFIG timerCfg; + PCODEC_MUTE_TIMER_CONTEXT timerCtx; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_MUTE_TIMER_CONTEXT); + attributes.ParentObject = circuitCtx->MuteElement; + + WDF_TIMER_CONFIG_INIT_PERIODIC(&timerCfg, CodecR_EvtMuteTimerFunc, 4000 /* 4sec in msec */); + + RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate(&timerCfg, &attributes, &muteCtx->Timer)); + + ASSERT(muteCtx->Timer); + + timerCtx = GetCodecMuteTimerContext(muteCtx->Timer); + ASSERT(timerCtx); + + timerCtx->MuteElement = circuitCtx->MuteElement; + } + + // + // Create 2nd custom circuit-element (volume element). + // + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxVolumeAssignLevel = CodecR_EvtVolumeAssignLevelCallback; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecR_EvtVolumeRetrieveLevelCallback; + + ACX_VOLUME_CONFIG volumeCfg; + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(circuit, &attributes, &volumeCfg, (ACXVOLUME *)&elements[1])); + + ASSERT(elements[1] != NULL); + CODEC_VOLUME_ELEMENT_CONTEXT *volumeCtx; + volumeCtx = GetCodecVolumeElementContext(elements[1]); + ASSERT(volumeCtx); + volumeCtx->VolumeLevel[0] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + volumeCtx->VolumeLevel[1] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING; + + circuitCtx->VolumeElement = (ACXVOLUME)elements[1]; + + // + // Testing async volume state change. + // + { + WDF_TIMER_CONFIG timerCfg; + PCODEC_VOLUME_TIMER_CONTEXT timerCtx; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_VOLUME_TIMER_CONTEXT); + attributes.ParentObject = circuitCtx->VolumeElement; + + WDF_TIMER_CONFIG_INIT_PERIODIC(&timerCfg, CodecR_EvtVolumeTimerFunc, 4500 /* 4.5sec in msec */); + + RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate(&timerCfg, &attributes, &volumeCtx->Timer)); + + ASSERT(volumeCtx->Timer); + + timerCtx = GetCodecVolumeTimerContext(volumeCtx->Timer); + ASSERT(timerCtx); + + timerCtx->VolumeElement = circuitCtx->VolumeElement; + } + + // + // Add the circuit elements + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + // PCM:44100 channel:2 24in32 + ACX_DATAFORMAT_CONFIG formatCfg; + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm44100c2_24in32); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT); + attributes.ParentObject = circuit; + + ACXDATAFORMAT formatPcm44100c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm44100c2_24in32)); + + CODEC_FORMAT_CONTEXT *formatCtx; + formatCtx = GetCodecFormatContext(formatPcm44100c2_24in32); + ASSERT(formatCtx); + + UNREFERENCED_PARAMETER(formatCtx); + + // PCM:48000 channel:2 24in32 + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm48000c2_24in32); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT); + attributes.ParentObject = circuit; + + ACXDATAFORMAT formatPcm48000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm48000c2_24in32)); + + formatCtx = GetCodecFormatContext(formatPcm48000c2_24in32); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + /////////////////////////////////////////////////////////// + // + // Create render pin. AcxCircuit creates the other pin by default. + // + + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = CodecR_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG pinCfg; + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + ACXPIN pin; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + CODEC_PIN_CONTEXT *pinCtx; + pinCtx = GetCodecPinContext(pin); + ASSERT(pinCtx); + + // + // Add our supported formats to the Default mode for the circuit + // + ACXDATAFORMATLIST formatList; + formatList = AcxPinGetRawDataFormatList(pin); + if (formatList == NULL) + { + status = STATUS_INSUFFICIENT_RESOURCES; + } + RETURN_NTSTATUS_IF_FAILED(status); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + + // Add render pin, using default pin id (0) + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create Bridge Pin. + // + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSNODETYPE_SPEAKER; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT); + attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + pinCtx = GetCodecPinContext(pin); + ASSERT(pinCtx); + + RETURN_NTSTATUS_IF_FAILED(AddJack(attributes, pin, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, RGB(0, 0, 0), AcxConnTypeAtapiInternal, AcxGeoLocFront, AcxGenLocPrimaryBox, AcxPortConnIntegratedDevice)); + + // Add render bridge pin + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + ConnectRenderCircuitElements(numElements, elements, circuit); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + status = STATUS_SUCCESS; + + + return status; +} + +_Use_decl_annotations_ +#pragma code_seg() +NTSTATUS +CodecR_EvtCircuitPowerUp ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState + ) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(PreviousState); + + CODEC_RENDER_CIRCUIT_CONTEXT * circuitCtx; + CODEC_MUTE_ELEMENT_CONTEXT * muteCtx; + CODEC_VOLUME_ELEMENT_CONTEXT * volumeCtx; + + // for testing. + circuitCtx = GetRenderCircuitContext(Circuit); + ASSERT(circuitCtx); + + ASSERT(circuitCtx->MuteElement); + muteCtx = GetCodecMuteElementContext(circuitCtx->MuteElement); + ASSERT(muteCtx); + + ASSERT(circuitCtx->VolumeElement); + volumeCtx = GetCodecVolumeElementContext(circuitCtx->VolumeElement); + ASSERT(volumeCtx); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitPowerDown ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState + ) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(TargetState); + + CODEC_RENDER_CIRCUIT_CONTEXT * circuitCtx; + CODEC_MUTE_ELEMENT_CONTEXT * muteCtx; + CODEC_VOLUME_ELEMENT_CONTEXT * volumeCtx; + + PAGED_CODE(); + + // for testing. + circuitCtx = GetRenderCircuitContext(Circuit); + ASSERT(circuitCtx); + + ASSERT(circuitCtx->MuteElement); + muteCtx = GetCodecMuteElementContext(circuitCtx->MuteElement); + ASSERT(muteCtx); + + ASSERT(circuitCtx->VolumeElement); + volumeCtx = GetCodecVolumeElementContext(circuitCtx->VolumeElement); + ASSERT(volumeCtx); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitCompositeCircuitInitialize( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_opt_ ACXOBJECTBAG CircuitProperties +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + + NTSTATUS status = STATUS_SUCCESS; + + if (CircuitProperties != NULL) + { + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + ULONG testUI4 = 0; + + status = AcxObjectBagRetrieveUI4(CircuitProperties, &TestUI4, &testUI4); + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitCompositeInitialize( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXOBJECTBAG CompositeProperties + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + + ASSERT(CompositeProperties); + + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID); + GUID uniqueId = {0}; + status = AcxObjectBagRetrieveGuid(CompositeProperties, &UniqueID, &uniqueId); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +CodecR_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVCodecLog); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(SignalProcessingMode); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + PCODEC_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + if (VarArguments) + { + // Get the variable arguments parameter and retrive the values set by the DSP object. + ULONG ui4Value = 0; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveUI4(VarArguments, &TestUI4, &ui4Value)); + + RETURN_NTSTATUS_IF_TRUE(ui4Value == 0, STATUS_UNSUCCESSFUL); + + ui4Value++; + + // Add the modified value back to object bag. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(VarArguments, &TestUI4, ui4Value)); + } + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + CodecR_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = Codec_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = Codec_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = Codec_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = Codec_EvtStreamPause; + streamCallbacks.EvtAcxStreamAssignDrmContentId = Codec_EvtStreamAssignDrmContentId; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_STREAM_CONTEXT); + attributes.EvtDestroyCallback = Codec_EvtStreamDestroy; + ACXSTREAM stream; + RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + CRenderStreamEngine *streamEngine = NULL; + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CRenderStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES); + + CODEC_STREAM_CONTEXT *streamCtx; + streamCtx = GetCodecStreamContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)streamEngine; + streamEngine = NULL; + + // + // Post stream creation initialization. + // + + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXELEMENT elements[2] = {0}; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + CODEC_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetCodecElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetCodecElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc new file mode 100644 index 00000000..0b1f9749 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc @@ -0,0 +1,12 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "ACX v1.0 Codec Audio Driver" +#define VER_INTERNALNAME_STR "SDCAVCodec.sys" +#define VER_ORIGINALFILENAME_STR "SDCAVCodec.sys" + +#include "common.ver" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp new file mode 100644 index 00000000..730f0553 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp @@ -0,0 +1,270 @@ +/*++ + + 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: + + StreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" + +#ifndef __INTELLISENSE__ +#include "streamengine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ) + : m_CurrentState(AcxStreamStateStop), + m_Stream(Stream), + m_StreamFormat(StreamFormat) +{ + PAGED_CODE(); + + KeQueryPerformanceCounter(&m_PerformanceCounterFrequency); +} + +#pragma code_seg() +CStreamEngine::~CStreamEngine() +{ +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStatePause; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStateStop; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Pause() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStatePause; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Run() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + if (m_CurrentState != AcxStreamStatePause) + { + status = STATUS_INVALID_STATE_TRANSITION; + return status; + } + + m_CurrentState = AcxStreamStateRun; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + UNREFERENCED_PARAMETER(DrmRights); + + // + // At this point the driver should enforce the new DrmRights. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // + // 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 AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay +) +{ + PAGED_CODE(); + + *FifoSize = 128; + *Delay = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat +) + : CStreamEngine(Stream, StreamFormat) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::~CRenderStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::PrepareHardware() +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + status = CStreamEngine::PrepareHardware(); + + // Add other init here. + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat +) + : CStreamEngine(Stream, StreamFormat) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::~CCaptureStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + + RETURN_NTSTATUS_IF_FAILED(ReadRegistrySettings()); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReadRegistrySettings() +{ + PAGED_CODE(); + + return STATUS_SUCCESS; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h new file mode 100644 index 00000000..906e21f3 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h @@ -0,0 +1,131 @@ +#pragma once + +#define HNSTIME_PER_MILLISECOND 10000 + +class CStreamEngine +{ +public: + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + virtual + #pragma code_seg() + ~CStreamEngine(); + +protected: + ACX_STREAM_STATE m_CurrentState; + ACXSTREAM m_Stream; + ACXDATAFORMAT m_StreamFormat; + LARGE_INTEGER m_PerformanceCounterFrequency; +}; + +class CRenderStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CRenderStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + +protected: + // data section. +}; + +class CCaptureStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + +protected: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReadRegistrySettings(); +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.cpp new file mode 100644 index 00000000..6a223c30 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.cpp @@ -0,0 +1,1715 @@ +/*++ + +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: + + AcpiReader.cpp + +Abstract: + + Implements Acpi reader module. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" + +#include <stdunk.h> + +#include "AcpiReader.h" + +#ifndef __INTELLISENSE__ +#include "AcpiReader.tmh" +#endif + +namespace ACPIREADER +{ + RECORDER_LOG AcpiReader::s_AcpiReaderLog { nullptr }; + ULONG AcpiReader::s_MemoryTag { 0 }; + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::_CreateAndInitialize(_In_ WDFDEVICE Device, _In_ RECORDER_LOG Log, _In_ ULONG MemoryTag) + { + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + AcpiReader * This{ nullptr }; + VOID * contextAddress; + + PAGED_CODE(); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, AcpiReader); + attributes.EvtDestroyCallback = EvtContextDestroy; + + status = WdfObjectAllocateContext(Device, &attributes, &contextAddress); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + s_AcpiReaderLog = Log; + s_MemoryTag = MemoryTag; + + This = new (contextAddress) AcpiReader(Device); + + exit: + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseGuid( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_bytes_(BufferLength) PVOID Buffer, + _In_ ULONG BufferLength + ) + /*++ + + Routine Description: + + This function parses the content of an ACPI method argument into a GUID. + + Arguments: + + Argument - Supplies the ACPI argument to parse. + + Buffer - Supplies a pointer to the buffer to store the GUID. + + BufferLength - Supplies the buffer size in bytes. + + Return Value: + + NTSTATUS + + --*/ + { + + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + DrvLogEnter(s_AcpiReaderLog); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_BUFFER) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected: %lu, Actual: %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_BUFFER, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + if (BufferLength < sizeof(GUID)) + { + status = STATUS_BUFFER_TOO_SMALL; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Buffer too small. Expected: %lu, Actual: %lu, %!STATUS!", sizeof(GUID), BufferLength, status); + ASSERT(FALSE); + goto exit; + } + + if (Argument->DataLength != sizeof(GUID)) + { + status = STATUS_ACPI_INVALID_ARGTYPE; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument DataLength. Expected: %lu, Actual: %lu, %!STATUS!", sizeof(GUID), Argument->DataLength, status); + ASSERT(FALSE); + goto exit; + } + + RtlCopyMemory((PUCHAR)Buffer, Argument->Data, Argument->DataLength); + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseULongLong( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_ PULONGLONG Value + ) + /*++ + Routine Description: + + This function parses the content of an ACPI method argument into a ULONGLONG. + + Arguments: + + Argument - Supplies the ACPI argument to parse. + + Value - Supplies a pointer to the buffer to store the ULONGLONG value. + + Return Value: + + NTSTATUS + + --*/ + { + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected: %lu, Actual: %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_INTEGER, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + if (Argument->DataLength != sizeof(ULONGLONG)) + { + status = STATUS_ACPI_INVALID_ARGTYPE; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument DataLength. Expected: %lu, Actual: %lu, %!STATUS!", sizeof(ULONGLONG), Argument->DataLength, status); + ASSERT(FALSE); + goto exit; + } + + RtlCopyMemory(Value, Argument->Data, Argument->DataLength); + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseULong( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_ PULONG Value + ) + /*++ + Routine Description: + + This function parses the content of an ACPI method argument into a ULONG. + + Arguments: + + Argument - Supplies the ACPI argument to parse. + + Value - Supplies a pointer to the buffer to store the ULONG value. + + Return Value: + + NTSTATUS + + --*/ + { + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected: %lu, Actual: %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_INTEGER, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + // Even though we are looking for a ULONG value, the DataLength will be set to ULONGLONG since we always use IOCTL_ACPI_EVAL_METHOD_EX + if (Argument->DataLength != sizeof(ULONGLONG)) + { + status = STATUS_ACPI_INVALID_ARGTYPE; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument DataLength. Expected: %lu, Actual: %lu, %!STATUS!", sizeof(ULONGLONG), Argument->DataLength, status); + ASSERT(FALSE); + goto exit; + } + + *Value = (ULONG)Argument->Argument; + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseString( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_opt_z_(ValueStringSize) char * ValueString, + _In_ ULONG ValueStringSize, + _Out_ PULONG PropertyValueSize + ) + /*++ + Routine Description: + + This function parses the content of an ACPI method argument into a string. + + Arguments: + + Argument - Supplies the ACPI argument to parse. + + ValueString - Buffer that will hold property value if found. + + ValueStringSize - Size of the output buffer. + + PropertyValueSize - Actual length of the property value. + + Return Value: + + NTSTATUS + + --*/ + { + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_STRING) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected %lu, Actual %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_STRING, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + *PropertyValueSize = Argument->DataLength; + + if (ValueStringSize == 0) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + else if (ValueStringSize < Argument->DataLength) + { + status = STATUS_BUFFER_TOO_SMALL; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Output buffer too small. Required %lu, Actual %lu, %!STATUS!", Argument->DataLength, ValueStringSize, status); + goto exit; + } +#pragma prefast(suppress:__WARNING_PRECONDITION_NULLTERMINATION_VIOLATION, "ACPI driver returns a NULL-terminated string.") + status = RtlStringCbCopyA(ValueString, ValueStringSize, (char *)Argument->Data); + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseBuffer( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_bytes_(ValueBufferSize) PVOID ValueBuffer, + _In_ ULONG ValueBufferSize, + _Out_ PULONG PropertyValueSize + ) + /*++ + Routine Description: + + This function parses the content of an ACPI method argument into a buffer. + + Arguments: + + Argument - Supplies the ACPI argument to parse. + + ValueBuffer - Buffer that will hold property value if found. + + ValueBufferSize - Size of the output buffer. + + PropertyValueSize - Actual length of the property value. + + Return Value: + + NTSTATUS + + --*/ + { + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_BUFFER) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected %lu, Actual %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_BUFFER, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + *PropertyValueSize = Argument->DataLength; + + if (ValueBufferSize < Argument->DataLength) + { + status = STATUS_BUFFER_TOO_SMALL; + + // DrvLogVerbose if ValueBufferSize is 0, which means it's being called to determine size. Otherwise, DrvLogError. + if (ValueBufferSize == 0) + { + DrvLogVerbose(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Output buffer too small. Required %lu, Actual %lu, %!STATUS!", Argument->DataLength, ValueBufferSize, status); + } + else + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Output buffer too small. Required %lu, Actual %lu, %!STATUS!", Argument->DataLength, ValueBufferSize, status); + } + + goto exit; + } + + RtlCopyMemory(ValueBuffer, Argument->Data, ValueBufferSize); + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParseULongArray( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_(ValueArrayCount) ULONG * ValueArray, + _In_ ULONG ValueArrayCount, + _Out_ PULONG PropertyValueArrayCount + ) + { + NTSTATUS status = STATUS_SUCCESS; + PACPI_METHOD_ARGUMENT currentArgument; + ULONG argumentIndex; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (Argument->Type != ACPI_METHOD_ARGUMENT_PACKAGE) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected Argument Type. Expected %lu, Actual %lu, %!STATUS!", ACPI_METHOD_ARGUMENT_PACKAGE, Argument->Type, status); + ASSERT(FALSE); + goto exit; + } + + // Initialize everything to 0 + for (ULONG i = 0; i < ValueArrayCount; ++i) + { + ValueArray[i] = 0; + } + + *PropertyValueArrayCount = 0; + currentArgument = (PACPI_METHOD_ARGUMENT)Argument->Data; + + for (argumentIndex = 0; (PUCHAR)currentArgument < (PUCHAR)Argument->Data + Argument->DataLength; argumentIndex++) + { +#pragma prefast(suppress:26014, "Incorrect Validation: ACPI driver returns well-formed data that doesn't extend past known length.") + if (currentArgument->Type != ACPI_METHOD_ARGUMENT_INTEGER) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected argument in an array, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + (*PropertyValueArrayCount)++; + currentArgument = ACPI_METHOD_NEXT_ARGUMENT(currentArgument); + } + + if (ValueArrayCount == 0) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + else if (ValueArrayCount < *PropertyValueArrayCount) + { + status = STATUS_BUFFER_TOO_SMALL; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Output array too small. Required elements %lu, Actual %lu, %!STATUS!", *PropertyValueArrayCount, ValueArrayCount, status); + goto exit; + } + + currentArgument = (PACPI_METHOD_ARGUMENT)Argument->Data; + for (argumentIndex = 0; (PUCHAR)currentArgument < (PUCHAR)Argument->Data + Argument->DataLength && argumentIndex < ValueArrayCount; argumentIndex++) + { + status = ParseULong(currentArgument, &ValueArray[argumentIndex]); + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected argument in an array, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + currentArgument = ACPI_METHOD_NEXT_ARGUMENT(currentArgument); + } + + exit: + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::EnumChildren( + _Out_ WDFMEMORY * EnumChildrenOutput + ) + /*++ + Routine Description: + + This function sends IOCTL_ACPI_ENUM_CHILDREN to ACPI to enumerate child devices. + + Arguments: + + EnumChildrenOutput - Supplies a resulting memory object. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status; + WDFMEMORY inputMem{ WDF_NO_HANDLE }; + PACPI_ENUM_CHILDREN_INPUT_BUFFER inputBuf; + size_t inputBufSize; + WDF_MEMORY_DESCRIPTOR inputMemDesc; + WDFMEMORY outputMem{ WDF_NO_HANDLE }; + PACPI_ENUM_CHILDREN_OUTPUT_BUFFER outputBuf; + size_t outputBufSize; + WDF_MEMORY_DESCRIPTOR outputMemDesc; + WDF_OBJECT_ATTRIBUTES attr; + ULONG attempts; + WDFIOTARGET acpiIoTarget; + WDF_REQUEST_SEND_OPTIONS sendOptions; + + PAGED_CODE(); + + DrvLogEnter(s_AcpiReaderLog); + + ASSERT(m_AcpiDevice); + + acpiIoTarget = WdfDeviceGetIoTarget(m_AcpiDevice); + + WDF_OBJECT_ATTRIBUTES_INIT(&attr); + attr.ParentObject = m_AcpiDevice; + + inputBufSize = sizeof(*inputBuf); + status = WdfMemoryCreate( + &attr, + NonPagedPoolNx, + s_MemoryTag, + inputBufSize, + &inputMem, + (PVOID*)&inputBuf); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! WdfMemoryCreate failed for inputBuf, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + RtlZeroMemory(inputBuf, inputBufSize); + inputBuf->Signature = ACPI_ENUM_CHILDREN_INPUT_BUFFER_SIGNATURE; + inputBuf->Flags = ENUM_CHILDREN_IMMEDIATE_ONLY; + + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMem, nullptr); + + // + // The initial output buffer allows one child only. It will be re-allocated + // with the returning "NumberOfChildren" bytes when IOCTL_ACPI_ENUM_CHILDREN + // fails with STATUS_BUFFER_OVERFLOW. The returning "NumberOfChildren" is + // not the number of children, but the required size in bytes. + // + outputBufSize = sizeof(*outputBuf); + attempts = 0; + + do + { + WDF_OBJECT_ATTRIBUTES_INIT(&attr); + attr.ParentObject = m_AcpiDevice; + + status = WdfMemoryCreate( + &attr, + NonPagedPoolNx, + s_MemoryTag, + outputBufSize, + &outputMem, + (PVOID*)&outputBuf); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! WdfMemoryCreate failed for outputBuf, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMem, nullptr); + + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, 0); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(ACPI_REQUEST_TIMEOUT_SEC)); + + status = WdfIoTargetSendIoctlSynchronously( + acpiIoTarget, + NULL, + IOCTL_ACPI_ENUM_CHILDREN, + &inputMemDesc, + &outputMemDesc, + &sendOptions, + nullptr); + + if (NT_SUCCESS(status)) + { + if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + // + // There must be at least one, because this device is included in the list. + // When IOCTL_ACPI_ENUM_CHILDREN succeeds, "NumberOfChildren" does have + // the number of children. (When the IOCTL fails, it's the required size + // in bytes.) + // + if (outputBuf->NumberOfChildren < 1) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! No child devices in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + // + // Return the output memory object. + // + *EnumChildrenOutput = outputMem; + outputMem = WDF_NO_HANDLE; + + break; + } + + if (status != STATUS_BUFFER_OVERFLOW) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! IOCTL_ACPI_ENUM_CHILDREN _BUFFER, %!STATUS!", status); + // No assert since this is common in sdca bringup + goto exit; + } + + if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + // + // When IOCTL_ACPI_ENUM_CHILDREN fails with STATUS_BUFFER_OVERFLOW, + // "NumberOfChildren" is not the number of children, but the required + // size in bytes. + // + outputBufSize = outputBuf->NumberOfChildren; + WdfObjectDelete(outputMem); + outputMem = WDF_NO_HANDLE; + attempts++; + } while (attempts < 2); + + exit: + + if (inputMem != WDF_NO_HANDLE) + { + WdfObjectDelete(inputMem); + inputMem = WDF_NO_HANDLE; + } + + if (outputMem != WDF_NO_HANDLE) + { + WdfObjectDelete(outputMem); + outputMem = WDF_NO_HANDLE; + } + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::EvaluateMethod( + _In_ LPCSTR MethodName, + _Out_ WDFMEMORY * ReturnMemory + ) + /*++ + Routine Description: + + This function sends IOCTL_ACPI_EVAL_METHOD_EX to ACPI to evaluate a method. + + Arguments: + + MethodName - Supplies a packed string identifying the method. + + ReturnMemory - Supplies the resulting memory object. + + Return Value: + + NTSTATUS code. + + --*/ + { + const ULONG InitialControlMethodOutputSize = 0x200; // 512 bytes + UCHAR attempts; + WDF_MEMORY_DESCRIPTOR inputDesc; + WDFMEMORY outputMem{ WDF_NO_HANDLE }; + PACPI_EVAL_OUTPUT_BUFFER outputBuf; + ULONG outputBufLength; + WDF_MEMORY_DESCRIPTOR outputDesc; + ULONG_PTR sizeReturned; + ACPI_EVAL_INPUT_BUFFER_EX inputBuf; + WDF_OBJECT_ATTRIBUTES attr; + WDFIOTARGET acpiIoTarget; + NTSTATUS status; + WDF_REQUEST_SEND_OPTIONS sendOptions; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + ASSERT(m_AcpiDevice); + + acpiIoTarget = WdfDeviceGetIoTarget(m_AcpiDevice); + + // + // Prepare an input buffer. + // + inputBuf.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX; + + status = RtlStringCchCopyA( + inputBuf.MethodName, + sizeof(inputBuf.MethodName), + MethodName); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! RtlStringCchCopyA failed to copy ACPI method name, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( + &inputDesc, + (PVOID)&inputBuf, + sizeof(ACPI_EVAL_INPUT_BUFFER_EX)); + + // + // Set the initial size for the output buffer to be allocated. + // + outputBuf = NULL; + outputBufLength = InitialControlMethodOutputSize; + attempts = 0; + + do + { + WDF_OBJECT_ATTRIBUTES_INIT(&attr); + attr.ParentObject = m_AcpiDevice; + + status = WdfMemoryCreate( + &attr, + NonPagedPoolNx, + s_MemoryTag, + outputBufLength, + &outputMem, + (PVOID*)&outputBuf); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! WdfMemoryCreate failed for %Iu bytes, %!STATUS!", outputBufLength, status); + ASSERT(FALSE); + goto exit; + } + + RtlZeroMemory(outputBuf, outputBufLength); + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( + &outputDesc, + (PVOID)outputBuf, + outputBufLength); + + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, 0); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(ACPI_REQUEST_TIMEOUT_SEC)); + + status = WdfIoTargetSendIoctlSynchronously( + acpiIoTarget, + NULL, + IOCTL_ACPI_EVAL_METHOD_EX, + &inputDesc, + &outputDesc, + &sendOptions, + &sizeReturned); + + if (NT_SUCCESS(status)) + { + // + // IOCTL_ACPI_EVAL_METHOD_EX succeeded. + // + if (sizeReturned == 0) + { + status = STATUS_UNSUCCESSFUL; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! IOCTL_ACPI_EVAL_METHOD_EX returned 0 byte, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + if (outputBuf->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! ACPI_EVAL_OUTPUT_BUFFER signature (0x%x) is incorrect, %!STATUS!", outputBuf->Signature, status); + ASSERT(FALSE); + goto exit; + } + + // + // Return the output memory object. + // + *ReturnMemory = outputMem; + outputMem = WDF_NO_HANDLE; + + break; + } + + if (status != STATUS_BUFFER_OVERFLOW) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "!FUNC! IOCTL_ACPI_EVAL_METHOD_EX failed , %!STATUS!", status); + // Failure is common when used alongside virtual stack + goto exit; + } + + // + // If the output buffer was insufficient, then re-allocate one with + // appropriate size and retry. + // + outputBufLength = outputBuf->Length; + WdfObjectDelete(outputMem); + outputMem = WDF_NO_HANDLE; + attempts++; + + if (attempts == 2) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! IOCTL_ACPI_EVAL_METHOD_EX has failed for %u times. Stopped retrying., %!STATUS!", attempts, status); + ASSERT(FALSE); + } + } while (attempts < 2); + + exit: + + if (outputMem != WDF_NO_HANDLE) + { + WdfObjectDelete(outputMem); + outputMem = WDF_NO_HANDLE; + } + + DrvLogExit(s_AcpiReaderLog); + + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::EvaluateAdr( + _In_opt_ LPCSTR ChildDeviceName, + _Out_ PULONGLONG Address + ) + /*++ + Routine Description: + + This function evaluates a _ADR method. + + Arguments: + + ChildDeviceName - Supplies a child device name. If Null, evaluate + the _ADR for the current device instead. + + Address - Returning the device address from _ADR. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status; + CHAR fullMethodName[MAX_PATH]; + WDFMEMORY outputMem{ WDF_NO_HANDLE }; + PACPI_EVAL_OUTPUT_BUFFER outputBuf; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!Address) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + if (ChildDeviceName != nullptr) + { + status = RtlStringCchPrintfA( + fullMethodName, + sizeof(fullMethodName), + "%s._ADR", + ChildDeviceName); + } + else + { + status = RtlStringCchCopyA( + fullMethodName, + sizeof(fullMethodName), + "_ADR"); + } + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! RtlStringCchPrintfA for creating method name _BUFFER, %!STATUS!", status); + ASSERT(FALSE); + goto exit; + } + + status = EvaluateMethod( + fullMethodName, + &outputMem); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! EvaluateMethod failed on [%s], %!STATUS!", fullMethodName, status); + ASSERT(FALSE); + goto exit; + } + + outputBuf = (PACPI_EVAL_OUTPUT_BUFFER)WdfMemoryGetBuffer(outputMem, NULL); + + if (outputBuf->Count < 1) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! _ADR of [%s] didn't return anything, %!STATUS!", fullMethodName, status); + ASSERT(FALSE); + goto exit; + } + + if (outputBuf->Argument[0].Type != ACPI_METHOD_ARGUMENT_INTEGER) + { + status = STATUS_ACPI_INVALID_DATA; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! _ADR of [%s] returned an unexpected argument of type %hu, %!STATUS!", fullMethodName, outputBuf->Argument[0].Type, status); + ASSERT(FALSE); + goto exit; + } + + status = ParseULongLong(outputBuf->Argument, Address); + + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Unexpected argument from _ADR of [%s], %!STATUS!", fullMethodName, status); + ASSERT(FALSE); + goto exit; + } + + exit: + if (outputMem != WDF_NO_HANDLE) + { + WdfObjectDelete(outputMem); + outputMem = WDF_NO_HANDLE; + } + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::EvaluateAdr( + _Out_ PULONGLONG Address + ) + /*++ + Routine Description: + + This function evaluates the _ADR method for the current device. + + Arguments: + + Address - Returning the device address from _ADR. + + Return Value: + + NTSTATUS code. + + --*/ + + { + NTSTATUS status; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + status = EvaluateAdr(nullptr, Address); + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetPropertyString( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_opt_z_(ValueStringSize) char * ValueString, + _In_ ULONG ValueStringSize, + _Out_ PULONG PropertyValueSize + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + string value for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + PropertySection - Specifies if property is under device property or hierarchical + data extension section. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + ValueString - Buffer that will hold property value if found. + + ValueStringSize - Size of the output buffer. + + PropertyValueSize - Actual length of the property value. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT propValueArg = NULL; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!PropertyName || !PropertyValueSize || (AcpiEvalOutputBuf == WDF_NO_HANDLE)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid PropertyName, PropertyValueSize or AcpiEvalOutputBuf, %!STATUS!", status); + goto exit; + } + if (ValueStringSize > 0 && !ValueString) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Null ValueString with non-zero ValueStringSize, %!STATUS!", status); + goto exit; + } + + status = GetProperty(PropertyName, PropertySection, AcpiEvalOutputBuf, &propValueArg); + + if (NT_SUCCESS(status)) + { + status = ParseString(propValueArg, ValueString, ValueStringSize, PropertyValueSize); + } + + exit: + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetPropertyULongLong( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_ PULONGLONG PropertyValue + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + ULONGLONG value for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + PropertySection - Specifies if property is under device property or hierarchical + data extension section. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + PropertyValue - Value of the property. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT propValueArg = NULL; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!PropertyName || !PropertyValue || (AcpiEvalOutputBuf == WDF_NO_HANDLE)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid PropertyName, PropertyValue or AcpiEvalOutputBuf, %!STATUS!", status); + goto exit; + } + + status = GetProperty(PropertyName, PropertySection, AcpiEvalOutputBuf, &propValueArg); + + if (NT_SUCCESS(status)) + { + status = ParseULongLong(propValueArg, PropertyValue); + } + + exit: + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetPropertyULong( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_ PULONG PropertyValue + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + ULONG value for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + PropertySection - Specifies if property is under device property or hierarchical + data extension section. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + PropertyValue - Value of the property. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT propValueArg = NULL; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!PropertyName || !PropertyValue || (AcpiEvalOutputBuf == WDF_NO_HANDLE)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid PropertyName, PropertyValue or AcpiEvalOutputBuf, %!STATUS!", status); + goto exit; + } + + status = GetProperty(PropertyName, PropertySection, AcpiEvalOutputBuf, &propValueArg); + + if (NT_SUCCESS(status)) + { + status = ParseULong(propValueArg, PropertyValue); + } + + exit: + DrvLogExit(s_AcpiReaderLog); + + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetPropertyBuffer( + _In_ LPCSTR PropertyName, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_bytes_(ValueBufferSize) PVOID ValueBuffer, + _In_ ULONG ValueBufferSize, + _Out_ PULONG PropertyValueSize + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + buffer value for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + ValueBuffer - Buffer that will hold property value if found. + + ValueBufferSize - Size of the output buffer. + + PropertyValueSize - Actual length of the property value. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT propValueArg = NULL; + char methodName[MAX_PATH]; + ULONG valueSize = 0; + WDFMEMORY bufferBlock = nullptr; + PACPI_EVAL_OUTPUT_BUFFER buffer; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!PropertyName || !PropertyValueSize || (AcpiEvalOutputBuf == WDF_NO_HANDLE)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid PropertyName, PropertyValueSize or AcpiEvalOutputBuf, %!STATUS!", status); + goto exit; + } + // Property we are searching is expected to return a buffer, + // so this property will be under Buffer UUID section + // ToUUID("EDB12DD0-363D-4085-A3D2-49522CA160C4"), + // Package() { + // Package { Property, "BUF0"} + // } + status = GetProperty(PropertyName, ACPI_METHOD_SECTION_BUFFER, AcpiEvalOutputBuf, &propValueArg); + + if (!NT_SUCCESS(status)) + { + // No need to log an error as it may be an optional property and not expected to be present all the time. + goto exit; + } + + // Value of the property will be method name + status = ParseString(propValueArg, methodName, sizeof(methodName), &valueSize); + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Failed to retrieve method name for %hs, %!STATUS!", PropertyName, status); + goto exit; + } + + // Evaluate method which will return contents of the buffer + // e.g. Evaluate method "BUF0" + status = EvaluateMethod(methodName, &bufferBlock); + if (!NT_SUCCESS(status)) + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Failed to evaluate method %hs, %!STATUS!", + methodName, + status); + goto exit; + } + + buffer = (PACPI_EVAL_OUTPUT_BUFFER)WdfMemoryGetBuffer(bufferBlock, NULL); + // This method must contain only one ACPI argument + if (buffer->Count != 1) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Method %hs has argument count %d, expected 1, %!STATUS!", + methodName, + buffer->Count, + status); + goto exit; + } + + status = ParseBuffer(buffer->Argument, ValueBuffer, ValueBufferSize, PropertyValueSize); + + exit: + if (bufferBlock != nullptr) + { + WdfObjectDelete(bufferBlock); + bufferBlock = nullptr; + } + + DrvLogExit(s_AcpiReaderLog); + + return status; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetPropertyULongArray( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_(ValueArrayCount) ULONG * ValueArray, + _In_ ULONG ValueArrayCount, + _Out_ PULONG PropertyValueArrayCount + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + an array of ULONGs for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + PropertySection - Specifies if property is under device property or hierarchical + data extension section. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + ValueArray - ULONG array that will hold property values if found. + + ValueArrayCount - Total count of elements in ValueArray. + + PropertyValueArrayCount - Valid count of elements in ValueArray. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT PropValueArg = NULL; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + if (!PropertyName || !PropertyValueArrayCount || (AcpiEvalOutputBuf == WDF_NO_HANDLE)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Invalid PropertyName, PropertyValueArrayCount or AcpiEvalOutputBuf, %!STATUS!", status); + goto exit; + } + + status = GetProperty(PropertyName, PropertySection, AcpiEvalOutputBuf, &PropValueArg); + + if (NT_SUCCESS(status)) + { + status = ParseULongArray(PropValueArg, ValueArray, ValueArrayCount, PropertyValueArrayCount); + } + + exit: + DrvLogExit(s_AcpiReaderLog); + + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::GetProperty( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue + ) + /*++ + Routine Description: + + This function searches for PropertyName in ACPI_EVAL_OUTPUT_BUFFER and returns + ACPI_METHOD_ARGUMENT for the property if found. + + Arguments: + + PropertyName - Property name to search for. + + PropertySection - Specifies if property is under device property, hierarchical + data extension or buffer section. + + AcpiEvalOutputBuf - WDFMEMORY containing ACPI_EVAL_OUTPUT_BUFFER in + which property needs to be searched. + + PropertyValue - ACPI_MEDHOD_ARGUMENT pointer to property value if the property was found. + + Return Value: + + NTSTATUS code. + + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_EVAL_OUTPUT_BUFFER Buffer; + PACPI_METHOD_ARGUMENT currentArgument; + ULONG argumentIndex; + GUID guid; + ACPI_METHOD_SECTION section = ACPI_METHOD_SECTION_UNKNOWN; + BOOL found = FALSE; + size_t PropertyLength; + size_t BufferLength; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + Buffer = (PACPI_EVAL_OUTPUT_BUFFER)WdfMemoryGetBuffer(AcpiEvalOutputBuf, &BufferLength); + + if (BufferLength < FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! WdfMemoryBuffer length %llu too short, %!STATUS!", BufferLength, status); + ASSERT(FALSE); + return status; + } + + if (Buffer->Length > BufferLength) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! ACPI_EVAL_OUTPUT_BUFFER length %lu exceeds WdfMemoryBuffer length %llu, %!STATUS!", Buffer->Length, BufferLength, status); + ASSERT(FALSE); + return status; + } + + // Method structure + // Name (Method, Package() { + // ToUUID("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"), + // Package () { + // Package (2) { Property, Value } + // : + // Package (2) { Property, Value } + // }, + // ToUUID("DBB8E3E6-5886-4BA6-8795-1319F52A966B"), + // Package() { + // Package { Property, Sub-Package} + // : + // Package { Property, Sub-Package} + // } + // ToUUID("EDB12DD0-363D-4085-A3D2-49522CA160C4"), + // Package() { + // Package { Property, Sub-Package} + // : + // Package { Property, Sub-Package} + // } + // } + + PropertyLength = strlen(PropertyName) + 1; // Add one for NULL terminator as ACPI_METHOD_ARGUMENT Datalength includes it. + + currentArgument = ACPI_EVAL_OUTPUT_BUFFER_ARGUMENTS_BEGIN(Buffer); + for (argumentIndex = 0; argumentIndex < Buffer->Count && !found; argumentIndex++) + { + if (((PUCHAR)currentArgument + ACPI_METHOD_ARGUMENT_LENGTH(0) > (PUCHAR)ACPI_EVAL_OUTPUT_BUFFER_ARGUMENTS_END(Buffer)) || + ((PUCHAR)currentArgument + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(currentArgument) > (PUCHAR)ACPI_EVAL_OUTPUT_BUFFER_ARGUMENTS_END(Buffer))) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! ACPI_METHOD_ARGUMENT outside of ACPI_EVAL_OUTPUT_BUFFER length, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + switch (currentArgument->Type) + { + case ACPI_METHOD_ARGUMENT_BUFFER: + + status = ParseGuid(currentArgument, &guid, sizeof(GUID)); + if (NT_SUCCESS(status) && guid == DSD_DEVICE_PROPERTIES_GUID) + { + section = ACPI_METHOD_SECTION_DEVICE_PROPERTIES; + } + else if (NT_SUCCESS(status) && guid == DSD_HIERARCHICAL_DATA_EXTENSION_GUID) + { + section = ACPI_METHOD_SECTION_HIERARCHICAL_DATA_EXTENSION; + } + else if (NT_SUCCESS(status) && guid == DSD_BUFFER_GUID) + { + section = ACPI_METHOD_SECTION_BUFFER; + } + else + { + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Skipping unexpected ACPI_METHOD_ARGUMENT_BUFFER argument, %!STATUS!", status); + ASSERT(FALSE); + section = ACPI_METHOD_SECTION_UNKNOWN; + } + break; + + case ACPI_METHOD_ARGUMENT_PACKAGE: + + // Caller specified the section in which to search property + // so further search only if this package is under that section + if (section == PropertySection) + { + // Parse sub-packages + status = ParsePropertiesPackage(PropertyName, PropertyLength, currentArgument, PropertyValue); + if (NT_SUCCESS(status)) + { + found = TRUE; + } + } + break; + + default: + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Skipping unexpected argument[%d] of type[%d]", argumentIndex, currentArgument->Type); + break; + } + currentArgument = ACPI_METHOD_NEXT_ARGUMENT(currentArgument); + } + + if (!found) + { + status = STATUS_NOT_FOUND; + } + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::ParsePropertiesPackage( + _In_ LPCSTR PropertyName, + _In_ size_t PropertyLength, + _In_ PACPI_METHOD_ARGUMENT Package, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue + ) + /*++ + Routine Description: + + This function searches for PropertyName in a package that contains + property packages. + + Arguments: + + PropertyName - Property name to search for. + + Package - Pointer to ACPI_METHOD_ARGUMENT containing package under + device property or hierarchical data extension section. + + PropertyValue - ACPI_MEDHOD_ARGUMENT pointer to property value if the property was found. + + Return Value: + + NTSTATUS code. + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT currentArgument; + ULONG argumentIndex; + BOOL found = FALSE; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + // Package structure + // Package () { + // Package (2) { Property, Value } + // : + // Package (2) { Property, Value } + // } + + if (Package->DataLength < ACPI_METHOD_ARGUMENT_LENGTH(0)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Package ACPI_METHOD_ARGUMENT too small, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + currentArgument = (PACPI_METHOD_ARGUMENT)Package->Data; + for (argumentIndex = 0 ; ((PUCHAR)currentArgument < (PUCHAR)Package->Data + Package->DataLength) && !found; argumentIndex++) + { + if (((PUCHAR)currentArgument + ACPI_METHOD_ARGUMENT_LENGTH(0) > (PUCHAR)Package->Data + Package->DataLength) || + ((PUCHAR)currentArgument + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(currentArgument) > (PUCHAR)Package->Data + Package->DataLength)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! ACPI_METHOD_ARGUMENT outside of package length, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + switch (currentArgument->Type) + { + case ACPI_METHOD_ARGUMENT_PACKAGE: + status = FindProperty(PropertyName, PropertyLength, currentArgument, PropertyValue); + if (NT_SUCCESS(status)) + { + found = TRUE; + } + break; + + default: + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Skipping unexpected argument[%d] of type[%d]", argumentIndex, currentArgument->Type); + break; + } + currentArgument = ACPI_METHOD_NEXT_ARGUMENT(currentArgument); + } + + if (!found) + { + status = STATUS_NOT_FOUND; + } + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + NTSTATUS + AcpiReader::FindProperty( + _In_ LPCSTR PropertyName, + _In_ size_t PropertyLength, + _In_ PACPI_METHOD_ARGUMENT Package, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue + ) + /*++ + Routine Description: + + This function searches for PropertyName in a package that contains + a property name and value. + + Arguments: + + PropertyName - Property name to search for. + + Package - Pointer to ACPI_METHOD_ARGUMENT containing package that has + property name and value. + + PropertyValue - ACPI_MEDHOD_ARGUMENT pointer to property value if the property was found. + + Return Value: + + NTSTATUS code. + --*/ + { + NTSTATUS status = STATUS_NOT_FOUND; + PACPI_METHOD_ARGUMENT propNameArgument; + PACPI_METHOD_ARGUMENT propValArgument; + + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + // Property package structure + // Package (2) { Property, Value } + + propNameArgument = (PACPI_METHOD_ARGUMENT)Package->Data; + propValArgument = ACPI_METHOD_NEXT_ARGUMENT(propNameArgument); + + if (Package->DataLength < ACPI_METHOD_ARGUMENT_LENGTH(0)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! Package ACPI_METHOD_ARGUMENT too small, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + if ((PUCHAR)propNameArgument + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(propNameArgument) > + (PUCHAR)Package + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(Package)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! prop name ACPI_METHOD_ARGUMENT outside of package length, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + if (propNameArgument->Type == ACPI_METHOD_ARGUMENT_STRING) + { + if ((PropertyLength == propNameArgument->DataLength) && + !_strnicmp(PropertyName, (char*)propNameArgument->Data, propNameArgument->DataLength)) + { + if ((PUCHAR)propValArgument + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(propValArgument) > + (PUCHAR)Package + ACPI_METHOD_ARGUMENT_LENGTH_FROM_ARGUMENT(Package)) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(s_AcpiReaderLog, FLAG_INIT, "%!FUNC! prop val ACPI_METHOD_ARGUMENT outside of package length, %!STATUS!", status); + ASSERT(FALSE); + return status; + } + + *PropertyValue = propValArgument; + status = STATUS_SUCCESS; + } + } + + DrvLogExit(s_AcpiReaderLog); + return status; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + VOID + AcpiReader::FreeBuffer( + _Inout_ WDFMEMORY * AcpiEvalOutputBuf + ) + /*++ + Routine Description: + + This function frees memory object. + + Arguments: + + AcpiEvalOutputBuf - Memory object to be freed. + + Return Value: + + VOID + + --*/ + { + DrvLogEnter(s_AcpiReaderLog); + + PAGED_CODE(); + + ASSERT(*AcpiEvalOutputBuf); + if ((*AcpiEvalOutputBuf) != WDF_NO_HANDLE) + { + WdfObjectDelete(*AcpiEvalOutputBuf); + *AcpiEvalOutputBuf = WDF_NO_HANDLE; + } + + DrvLogExit(s_AcpiReaderLog); + return; + } + + _Use_decl_annotations_ + PAGED_CODE_SEG + VOID + AcpiReader::EvtContextDestroy(WDFOBJECT Object) + { + PAGED_CODE(); + + AcpiReader * context = GetAcpiReaderDeviceContext(Object); + context->~AcpiReader(); + } +} // namespace ACPIREADER diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.h new file mode 100644 index 00000000..5c9ceee8 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AcpiReader.h @@ -0,0 +1,297 @@ +/*++ + +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: + + AcpiReader.h + +Abstract: + + Contains ACPI reader module. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +#ifndef _ACPIREADER_H_ +#define _ACPIREADER_H_ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <acpiioct.h> + +// Number of seconds for ACPI request timeout. +#define ACPI_REQUEST_TIMEOUT_SEC 5 + +// +// Device properties UUID in the ACPI methods. +// {DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301} +// +DEFINE_GUID(DSD_DEVICE_PROPERTIES_GUID, + 0xDAFFD814, 0x6EBA, 0x4D8C, 0x8A, 0x91, 0xBC, 0x9B, 0xBF, 0x4A, 0xA3, 0x01); + +// +// Hierarchical data extension UUID in the ACPI methods. +// {DBB8E3E6-5886-4BA6-8795-1319F52A966B} +// + +DEFINE_GUID(DSD_HIERARCHICAL_DATA_EXTENSION_GUID, + 0xDBB8E3E6, 0x5886, 0x4BA6, 0x87, 0x95, 0x13, 0x19, 0xF5, 0x2A, 0x96, 0x6B); + +// +// Buffer UUID in ACPI methods. +// {EDB12DD0-363D-4085-A3D2-49522CA160C4} +// + +DEFINE_GUID(DSD_BUFFER_GUID, + 0xEDB12DD0, 0x363D, 0x4085, 0xA3, 0xD2, 0x49, 0x52, 0x2C, 0xA1, 0x60, 0xC4); + +namespace ACPIREADER +{ + typedef enum + { + ACPI_METHOD_SECTION_UNKNOWN = 0, + ACPI_METHOD_SECTION_DEVICE_PROPERTIES = 1, + ACPI_METHOD_SECTION_HIERARCHICAL_DATA_EXTENSION = 2, + ACPI_METHOD_SECTION_BUFFER = 3 + } ACPI_METHOD_SECTION; + + class AcpiReader + { + private: + WDFDEVICE m_AcpiDevice{ nullptr }; + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseULongLong( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_ PULONGLONG Value); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseULong( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_ PULONG Value); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseString( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_opt_z_(ValueStringSize) char * ValueString, + _In_ ULONG ValueStringSize, + _Out_ PULONG PropertyValueSize); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseBuffer( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_bytes_(ValueBufferSize) PVOID ValueBuffer, + _In_ ULONG ValueBufferSize, + _Out_ PULONG PropertyValueSize); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseGuid( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_bytes_(BufferLength) PVOID Buffer, + _In_ ULONG BufferLength); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetProperty( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParsePropertiesPackage( + _In_ LPCSTR PropertyName, + _In_ size_t PropertyLength, + _In_ PACPI_METHOD_ARGUMENT Package, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FindProperty( + _In_ LPCSTR PropertyName, + _In_ size_t PropertyLength, + _In_ PACPI_METHOD_ARGUMENT Package, + _Outptr_result_maybenull_ PACPI_METHOD_ARGUMENT * PropertyValue); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ParseULongArray( + _In_ PACPI_METHOD_ARGUMENT Argument, + _Out_writes_(ValueArrayCount) ULONG * ValueArray, + _In_ ULONG ValueArrayCount, + _Out_ PULONG PropertyValueArrayCount); + + public: + static + _Must_inspect_result_ + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + _CreateAndInitialize(_In_ WDFDEVICE Device, _In_ RECORDER_LOG Log, _In_ ULONG MemoryTag); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + EnumChildren( + _Out_ WDFMEMORY * EnumChildrenOutput); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + EvaluateMethod( + _In_ LPCSTR MethodName, + _Out_ WDFMEMORY * ReturnMemory); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + EvaluateAdr( + _In_opt_ LPCSTR ChildDeviceName, + _Out_ PULONGLONG Address); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + EvaluateAdr( + _Out_ PULONGLONG Address); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPropertyULongLong( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_ PULONGLONG PropertyValue); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPropertyULong( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_ PULONG PropertyValue); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPropertyString( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_opt_z_(ValueStringSize) char * ValueString, + _In_ ULONG ValueStringSize, + _Out_ PULONG PropertyValueSize); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPropertyBuffer( + _In_ LPCSTR PropertyName, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_bytes_(ValueBufferSize) PVOID ValueBuffer, + _In_ ULONG ValueBufferSize, + _Out_ PULONG PropertyValueSize); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPropertyULongArray( + _In_ LPCSTR PropertyName, + _In_ ACPI_METHOD_SECTION PropertySection, + _In_ WDFMEMORY AcpiEvalOutputBuf, + _Out_writes_(ValueArrayCount) ULONG * ValueArray, + _In_ ULONG ValueArrayCount, + _Out_ PULONG PropertyValueArrayCount); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + FreeBuffer( + _Inout_ WDFMEMORY* AcpiEvalOutputBuf); + + protected: + + static + RECORDER_LOG s_AcpiReaderLog; + + static + ULONG s_MemoryTag; + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + EVT_WDF_OBJECT_CONTEXT_DESTROY + EvtContextDestroy; + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + AcpiReader(_In_ WDFDEVICE Device) : m_AcpiDevice(Device) { PAGED_CODE(); } + + // Placement-new to construct the object inside the WDF context space. + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void* + operator new ( + _In_ size_t /* SizeInBytes */, + _In_ void* ContextMemory + ) + { + PAGED_CODE(); + // We already have the memory courtesy of WDF so we don't have to allocate anything. + return ContextMemory; + } + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + operator delete ( + _In_ void* /* ContextMemory */ + ) + { + PAGED_CODE(); + // Since we didn't allocate the memory, don't try to deallocate it. + } + + }; + + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(AcpiReader, GetAcpiReaderDeviceContext) +} +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +#endif // _ACPIREADER_H_ diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.cpp new file mode 100644 index 00000000..79764cdc --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.cpp @@ -0,0 +1,384 @@ +/*++ + + 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: + + AudioModule.cpp + +Abstract: + + Implementation of general purpose audio module property handlers + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "audiomodule.h" +#include "stdunk.h" +#include <ks.h> + +AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[] = +{ + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_SET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE0_CONTEXT, Parameter1), + VT_UI4, + AudioModule0_ValidParameterList, + SIZEOF_ARRAY(AudioModule0_ValidParameterList) + }, + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE0_CONTEXT, Parameter2), + VT_UI1, + NULL, + 0 + }, +}; + +AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE1_CONTEXT, Parameter1), + VT_UI1, + AudioModule1_ValidParameterList, + SIZEOF_ARRAY(AudioModule1_ValidParameterList) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE1_CONTEXT, Parameter2), + VT_UI8, + NULL, + 0 + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE1_CONTEXT, Parameter3), + VT_UI4, + NULL, + 0 + }, +}; + +AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE2_CONTEXT, Parameter1), + VT_UI4, + AudioModule2_ValidParameterList, + SIZEOF_ARRAY(AudioModule2_ValidParameterList) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(DSP_AUDIOMODULE2_CONTEXT, Parameter2), + VT_UI2, + NULL, + 0 + }, +}; + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbFullProperty = 0; + ULONG cbDataListSize = 0; + + PAGED_CODE(); + + ASSERT(ParameterInfo); + ASSERT(BufferCb); + + // + // Compute total size of property. + // + ntStatus = RtlULongMult(ParameterInfo->Size, + ParameterInfo->ValidSetCount, + &cbDataListSize); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + ntStatus = RtlULongAdd(cbDataListSize, + (ULONG)(sizeof(KSPROPERTY_DESCRIPTION) + + sizeof(KSPROPERTY_MEMBERSHEADER)), + &cbFullProperty); + + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + // + // Return the info the caller is asking for. + // + if (*BufferCb == 0) + { + // caller wants to know the size of the buffer. + *BufferCb = cbFullProperty; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (*BufferCb >= (sizeof(KSPROPERTY_DESCRIPTION))) + { + PKSPROPERTY_DESCRIPTION propDesc = PKSPROPERTY_DESCRIPTION(Buffer); + + propDesc->AccessFlags = ParameterInfo->AccessFlags; + propDesc->DescriptionSize = cbFullProperty; + propDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + propDesc->PropTypeSet.Id = ParameterInfo->VtType; + propDesc->PropTypeSet.Flags = 0; + propDesc->MembersListCount = 1; + propDesc->Reserved = 0; + + // if return buffer can also hold a list description, return it too + if(*BufferCb >= cbFullProperty) + { + // fill in the members header + PKSPROPERTY_MEMBERSHEADER members = + PKSPROPERTY_MEMBERSHEADER(propDesc + 1); + + members->MembersFlags = KSPROPERTY_MEMBER_VALUES; + members->MembersSize = ParameterInfo->Size; + members->MembersCount = ParameterInfo->ValidSetCount; + members->Flags = KSPROPERTY_MEMBER_FLAG_DEFAULT; + + // fill in valid array. + BYTE* array = (BYTE*)(members + 1); + + RtlCopyMemory(array, ParameterInfo->ValidSet, cbDataListSize); + + // set the return value size + *BufferCb = cbFullProperty; + } + else + { + *BufferCb = sizeof(KSPROPERTY_DESCRIPTION); + } + } + else if(*BufferCb >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG accessFlags = PULONG(Buffer); + + *BufferCb = sizeof(ULONG); + *accessFlags = ParameterInfo->AccessFlags; + } + else + { + *BufferCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + return ntStatus; +} + +#pragma code_seg("PAGE") +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ) +{ + PAGED_CODE(); + + ULONG i = 0; + ULONG j = 0; + BOOLEAN validParam = FALSE; + + // + // Validate buffer ptr and size. + // + if (Buffer == NULL || BufferCb == 0) + { + validParam = FALSE; + goto exit; + } + + // + // Check its size. + // + if (BufferCb < ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + + // + // Check the valid list. + // + if (ParameterInfo->ValidSet && ParameterInfo->ValidSetCount) + { + BYTE* buffer = (BYTE*)ParameterInfo->ValidSet; + BYTE* pattern = (BYTE*)Buffer; + + // + // Scan the valid list. + // + for (i = 0; i < ParameterInfo->ValidSetCount; ++i) + { + for (j=0; j < ParameterInfo->Size; ++j) + { + if (buffer[j] != pattern[j]) + { + break; + } + } + + if (j == ParameterInfo->Size) + { + // got a match. + break; + } + + buffer += ParameterInfo->Size; + } + + // + // If end of list, we didn't find the value. + // + if (i == ParameterInfo->ValidSetCount) + { + validParam = FALSE; + goto exit; + } + } + else + { + // + // Negative-testing support. Fail request if value is -1. + // + BYTE* buffer = (BYTE*)Buffer; + + for (i = 0; i < ParameterInfo->Size; ++i) + { + if (buffer[i] != 0xFF) + { + break; + } + } + + // + // If value is -1, return error. + // + if (i == ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + } + + validParam = TRUE; + +exit: + return validParam; +} + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ParameterId); + + *ParameterChanged = FALSE; + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + return AudioModule_GenericHandler_BasicSupport(ParameterInfo, OutBuffer, OutBufferCb); + } + + ULONG cbMinSize = ParameterInfo->Size; + + if (Verb & KSPROPERTY_TYPE_GET) + { + // Verify module parameter supports 'get'. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_GET)) + { + *OutBufferCb = 0; + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Verify value size + if (*OutBufferCb == 0) + { + *OutBufferCb = cbMinSize; + return STATUS_BUFFER_OVERFLOW; + } + if (*OutBufferCb < cbMinSize) + { + *OutBufferCb = 0; + return STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory(OutBuffer, CurrentValue, ParameterInfo->Size); + *OutBufferCb = cbMinSize; + return STATUS_SUCCESS; + } + } + else if (Verb & KSPROPERTY_TYPE_SET) + { + *OutBufferCb = 0; + + // Verify it is a write prop. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_SET)) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Validate parameter. + if (!IsAudioModuleParameterValid(ParameterInfo, InBuffer, InBufferCb)) + { + return STATUS_INVALID_PARAMETER; + } + + if (ParameterInfo->Size != + RtlCompareMemory(CurrentValue, InBuffer, ParameterInfo->Size)) + { + RtlCopyMemory(CurrentValue, InBuffer, ParameterInfo->Size); + *ParameterChanged = TRUE; + } + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_DEVICE_REQUEST; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.h new file mode 100644 index 00000000..9369f835 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/AudioModule.h @@ -0,0 +1,216 @@ +/*++ + +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: + + AudioModule.h + +Abstract: + + Contains audio modules definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#ifndef _AUDIOMODULE_H_ +#define _AUDIOMODULE_H_ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +// Audio module definitions + +// +// Audio module instance defintion. +// This sample driver generates an instance id by combinding the +// configuration set # for a class module id with the instance of that +// configuration. Real driver should use a more robust scheme, such as +// an indirect mapping from/to an instance id to/from a configuration set +// + location in the pipeline + any other info the driver needs. +// +// top 8 bits reserved for use by aggregation +// next 12 bits are the config id mask +// bottom 12 bits instance id +#define AUDIOMODULE_CLASS_CFG_ID_MASK 0xFFF +#define AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK 0xFFF + +#define AUDIOMODULE_INSTANCE_ID(ClassCfgId, ClassCfgInstanceId) \ + ((ULONG(ClassCfgId & AUDIOMODULE_CLASS_CFG_ID_MASK) << 12) | \ + (ULONG(ClassCfgInstanceId & AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK))) + +#define AUDIOMODULE_GET_CLASSCFGID(InstanceId) \ + (ULONG(InstanceId) >> 12 & AUDIOMODULE_CLASS_CFG_ID_MASK) + +enum AudioModule_Parameter { + AudioModuleParameter1 = 0, + AudioModuleParameter2, + AudioModuleParameter3 +}; + +typedef struct _AUDIOMODULE_CUSTOM_COMMAND { + ULONG Verb; // get, set and support + AudioModule_Parameter ParameterId; +} AUDIOMODULE_CUSTOM_COMMAND, *PAUDIOMODULE_CUSTOM_COMMAND; + +enum AudioModule_Notification_Type { + AudioModuleParameterChanged = 0, +}; + +typedef struct _AUDIOMODULE_CUSTOM_NOTIFICATION { + ULONG Type; + union { + struct { + ULONG ParameterId; + } ParameterChanged; + }; +} AUDIOMODULE_CUSTOM_NOTIFICATION, *PAUDIOMODULE_CUSTOM_NOTIFICATION; + +#define AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION 0x00000001 + +typedef struct _DSP_AUDIOMODULE0_CONTEXT { + ACXPNPEVENT Event; + ULONG Parameter1; + BYTE Parameter2; + ULONG InstanceId; +} DSP_AUDIOMODULE0_CONTEXT, *PDSP_AUDIOMODULE0_CONTEXT; + +typedef struct _DSP_AUDIOMODULE1_CONTEXT { + ACXPNPEVENT Event; + BYTE Parameter1; + ULONGLONG Parameter2; + DWORD Parameter3; + ULONG InstanceId; +} DSP_AUDIOMODULE1_CONTEXT, *PDSP_AUDIOMODULE1_CONTEXT; + +typedef struct _DSP_AUDIOMODULE2_CONTEXT { + ACXPNPEVENT Event; + ULONG Parameter1; + USHORT Parameter2; + ULONG InstanceId; +} DSP_AUDIOMODULE2_CONTEXT, *PDSP_AUDIOMODULE2_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_AUDIOMODULE0_CONTEXT, GetDspAudioModule0Context); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_AUDIOMODULE1_CONTEXT, GetDspAudioModule1Context); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_AUDIOMODULE2_CONTEXT, GetDspAudioModule2Context); + +typedef struct _AUDIOMODULE_PARAMETER_INFO +{ + USHORT AccessFlags; // get/set/basic-support attributes. + USHORT Flags; + ULONG Size; + DWORD VtType; + PVOID ValidSet; + ULONG ValidSetCount; +} AUDIOMODULE_PARAMETER_INFO, *PAUDIOMODULE_PARAMETER_INFO; + +// +// Module 0 definitions +// +#define AUDIOMODULE0DESCRIPTION L"Generic system module" +#define AUDIOMODULE0_MAJOR 0x1 +#define AUDIOMODULE0_MINOR 0X0 + +// {BD7CDC7F-F52E-4A95-B026-586926056128} +static const GUID AudioModule0Id = +{ 0xbd7cdc7f, 0xf52e, 0x4a95, { 0xb0, 0x26, 0x58, 0x69, 0x26, 0x5, 0x61, 0x28 } }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND DspR_EvtProcessCommand0; + +static +ULONG AudioModule0_ValidParameterList[] = +{ + 1, 2, 5 +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[2]; + +// +// Module 1 definitions +// +static +BYTE AudioModule1_ValidParameterList[] = +{ + 0, 1, 2 +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[3]; + +#define AUDIOMODULE1DESCRIPTION L"Module 1" +#define AUDIOMODULE1_MAJOR 0x2 +#define AUDIOMODULE1_MINOR 0X1 + +// {2803D255-6175-40A4-A572-ECF9FF6F07A9} +static const GUID AudioModule1Id = +{ 0x2803d255, 0x6175, 0x40a4, { 0xa5, 0x72, 0xec, 0xf9, 0xff, 0x6f, 0x7, 0xa9 } }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND DspR_EvtProcessCommand1; + +// +// Module 2 definitions +// +static +ULONG AudioModule2_ValidParameterList[] = +{ + 1, 0xfffffffe +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[2]; + +#define AUDIOMODULE2DESCRIPTION L"Module 2" +#define AUDIOMODULE2_MAJOR 0x2 +#define AUDIOMODULE2_MINOR 0X0 + +// {2225578F-DF3B-40D8-BE80-031E1649DCC4} +static const GUID AudioModule2Id = +{ 0x2225578f, 0xdf3b, 0x40d8, { 0xbe, 0x80, 0x3, 0x1e, 0x16, 0x49, 0xdc, 0xc4 } }; + + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND DspR_EvtProcessCommand2; + +// General purpose helper functions + +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ); + +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ); + +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ); + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +#endif // _AUDIOMODULE_H_ diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.cpp new file mode 100644 index 00000000..94d94843 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.cpp @@ -0,0 +1,1467 @@ +/*++ + + 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: + + CircuitHelper.cpp + +Abstract: + + This module contains helper functions for render.cpp and capture.cpp files. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "CircuitHelper.h" +#include "TestProperties.h" +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "CircuitHelper.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS CreateCaptureCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +) +{ + + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + // Circuit Component ID already assigned by the device handler + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(CircuitInit, &CircuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(CircuitInit, AcxCircuitTypeCapture); + + // + // Assign the circuit's pnp-power callbacks. + // + { + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = DspC_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = DspC_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(CircuitInit, &powerCallbacks); + } + + // + // Assign the circuit's composite callbacks. + // + { + ACX_CIRCUIT_COMPOSITE_CALLBACKS compositeCallbacks; + ACX_CIRCUIT_COMPOSITE_CALLBACKS_INIT(&compositeCallbacks); + compositeCallbacks.EvtAcxCircuitCompositeCircuitInitialize = DspC_EvtCircuitCompositeCircuitInitialize; + compositeCallbacks.EvtAcxCircuitCompositeInitialize = DspC_EvtCircuitCompositeInitialize; + AcxCircuitInitSetAcxCircuitCompositeCallbacks(CircuitInit, &compositeCallbacks); + } + + + // + // Add pre-process callbacks. + // +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + Dsp_EvtStreamGetStreamCountRequestPreprocess, + (ACXCONTEXT)Device, + AcxRequestTypeProperty, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CINSTANCES)); +#endif // ACX_WORKAROUND_ACXPIN_01 + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + DspC_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + CircuitInit, + DspC_EvtCircuitCreateStream)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(CircuitInit, + CircuitProperties, + CircuitPropertiesCount)); + */ + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_CIRCUIT_CONTEXT); + attributes.EvtCleanupCallback = DspC_EvtCircuitContextCleanup; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &CircuitInit, Circuit)); + + return status; +} + +PAGED_CODE_SEG +VOID Dsp_EvtPropertyResourceGroup( + _In_ ACXOBJECT Circuit, + _In_ WDFREQUEST Request +) +{ + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS params; + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + PAUDIORESOURCEMANAGEMENT_RESOURCEGROUP resourceGroup = + (PAUDIORESOURCEMANAGEMENT_RESOURCEGROUP)params.Parameters.Property.Value; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Circuit %p received KSPROPERTY_AUDIORESOURCEMANAGEMENT_RESOURCEGROUP with group \"%ls\" %ls", + Circuit, resourceGroup->ResourceGroupName, resourceGroup->ResourceGroupAcquired ? L"Acquired" : L"Released"); + + WdfRequestComplete(Request, STATUS_SUCCESS); +} + + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +) +{ + + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + // Circuit Component ID already assigned by the device handler + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(CircuitInit, &CircuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(CircuitInit, AcxCircuitTypeRender); + + // + // Assign the circuit's pnp-power callbacks. + // + { + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = DspR_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = DspR_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(CircuitInit, &powerCallbacks); + } + + // + // Assign the circuit's composite callbacks. + // + { + ACX_CIRCUIT_COMPOSITE_CALLBACKS compositeCallbacks; + ACX_CIRCUIT_COMPOSITE_CALLBACKS_INIT(&compositeCallbacks); + compositeCallbacks.EvtAcxCircuitCompositeCircuitInitialize = DspR_EvtCircuitCompositeCircuitInitialize; + compositeCallbacks.EvtAcxCircuitCompositeInitialize = DspR_EvtCircuitCompositeInitialize; + AcxCircuitInitSetAcxCircuitCompositeCallbacks(CircuitInit, &compositeCallbacks); + } + + // + // Assign properties handled by the circuit. + // + { + ACX_PROPERTY_ITEM RenderCircuitProperties[] = + { + { + &KSPROPSETID_AudioResourceManagement, + KSPROPERTY_AUDIORESOURCEMANAGEMENT_RESOURCEGROUP, + ACX_PROPERTY_ITEM_FLAG_SET, + Dsp_EvtPropertyResourceGroup, + nullptr, + 0, + sizeof(AUDIORESOURCEMANAGEMENT_RESOURCEGROUP), + 0 + }, + }; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(CircuitInit, RenderCircuitProperties, ARRAYSIZE(RenderCircuitProperties))); + } + // + // Add pre-process callbacks. + // +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + Dsp_EvtStreamGetStreamCountRequestPreprocess, + (ACXCONTEXT)Device, + AcxRequestTypeProperty, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_CINSTANCES)); +#endif + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_02 + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + Dsp_EvtStreamProposeDataFormatRequestPreprocess, + (ACXCONTEXT)Device, + AcxRequestTypeProperty, + &KSPROPSETID_Pin, + KSPROPERTY_PIN_PROPOSEDATAFORMAT)); +#endif // ACX_WORKAROUND_ACXPIN_02 + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + CircuitInit, + DspR_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + CircuitInit, + DspR_EvtCircuitCreateStream)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(CircuitInit, + CircuitProperties, + CircuitPropertiesCount)); + */ + + // + // Disable ACX remote stream handling. + // This is for testing only b/c by creating an explicit stream-bridge below, + // the default ACX behavior for stream-bridge is automatically disabled. + // + AcxCircuitInitDisableDefaultStreamBridgeHandling(CircuitInit); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_CIRCUIT_CONTEXT); + attributes.EvtCleanupCallback = DspR_EvtCircuitContextCleanup; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &CircuitInit, Circuit)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_DATAFORMAT_CONFIG formatCfg; + ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &WaveFormat); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_FORMAT_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, Format)); + + ASSERT((*Format) != NULL); + DSP_FORMAT_CONTEXT* formatCtx; + formatCtx = GetDspFormatContext(*Format); + ASSERT(formatCtx); + UNREFERENCED_PARAMETER(formatCtx); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS CreatePin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ ULONG PinStreamCount, + _In_ bool Mic, + _Out_ ACXPIN* Pin +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACX_PIN_CONFIG pinCfg; + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = PinType; + pinCfg.Communication = Communication; + pinCfg.Category = Category; + pinCfg.PinCallbacks = PinCallbacks; + +// See description in private.h +#ifndef ACX_WORKAROUND_ACXPIN_01 + pinCfg->MaxStreams = PinStreamCount; +#endif + + ACX_MICROPHONE_CONFIG micCfg; + ACX_INTERLEAVED_AUDIO_FORMAT_INFORMATION InterleavedFormat; + + if (Mic) + { + ACX_MICROPHONE_CONFIG_INIT(&micCfg); + ACX_INTERLEAVED_AUDIO_FORMAT_INFORMATION_INIT(&InterleavedFormat); + + InterleavedFormat.PrimaryChannelCount = 2; + InterleavedFormat.PrimaryChannelStartPosition = 0; + InterleavedFormat.PrimaryChannelMask = 0; + InterleavedFormat.InterleavedChannelCount = 2; + InterleavedFormat.InterleavedChannelStartPosition = 2; + InterleavedFormat.InterleavedChannelMask = KSAUDIO_SPEAKER_STEREO; + + micCfg.InterleavedFormat = &InterleavedFormat; + + pinCfg.Flags |= AcxPinConfigMicrophoneConfigSpecified; + pinCfg.u.MicrophoneConfig = &micCfg; + } + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PIN_CONTEXT); + attributes.EvtCleanupCallback = DspR_EvtPinContextCleanup; + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(Circuit, &attributes, &pinCfg, Pin)); + ASSERT(Pin != NULL); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + { + PDSP_PIN_CONTEXT pinCtx = GetDspPinContext(*Pin); + pinCtx->MaxStreams = PinStreamCount; + pinCtx->CurrentStreamsCount = 0; + } +#endif + + return status; +} + +PAGED_CODE_SEG +NTSTATUS RetrieveProperties( + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _Out_ PULONG EndpointID +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId); + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DataPortNumber); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + // Create object bag from the CompositeProperties + ACXOBJECTBAG compositeProperties; + ACX_OBJECTBAG_CONFIG propConfig; + ACX_OBJECTBAG_CONFIG_INIT(&propConfig); + propConfig.Handle = CircuitConfig->CompositeProperties; + propConfig.Flags |= AcxObjectBagConfigOpenWithHandle; + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &propConfig, &compositeProperties)); + + auto cleanupCompositeProperties = scope_exit([=]() { + WdfObjectDelete(compositeProperties); + } + ); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveUI4(compositeProperties, &EndpointId, EndpointID)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DetermineSpecialStreamDetailsFromVendorProperties( + _In_ ACXCIRCUIT Circuit, + _In_ AcpiReader * Acpi, + _In_ HANDLE CircuitPropertiesHandle + ) +{ + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(VendorPropertiesBlock); + WDFMEMORY vendorPropertiesBlock = NULL; + DSP_CIRCUIT_CONTEXT* circuitCtx; + NTSTATUS status = STATUS_SUCCESS; + PSDCA_PATH_DESCRIPTORS2 pPathDesc2 = nullptr; + + PAGED_CODE(); + + ACX_OBJECTBAG_CONFIG propConfig; + ACXOBJECTBAG circuitProperties; + ACX_OBJECTBAG_CONFIG_INIT(&propConfig); + propConfig.Handle = CircuitPropertiesHandle; + propConfig.Flags |= AcxObjectBagConfigOpenWithHandle; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &propConfig, &circuitProperties)); + + auto cleanupPropConfig = scope_exit([=]() + { + WdfObjectDelete(circuitProperties); + }); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveBlob(circuitProperties, &VendorPropertiesBlock, NULL, &vendorPropertiesBlock)); + + auto cleanup1 = scope_exit([&vendorPropertiesBlock] () + { + if (vendorPropertiesBlock != NULL) + { + WdfObjectDelete(vendorPropertiesBlock); + vendorPropertiesBlock = NULL; + } + }); + + // + // The below code would be replaced in a real DSP driver (or modified to use vendor-specific properties) + // + circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx); + + for (ULONG i = (UINT)SpecialStreamTypeUltrasoundRender; i < (UINT)SpecialStreamType_Count; i++) + { + SDCA_PATH path = SdcaPathFromSpecialStreamType((SDCA_SPECIALSTREAM_TYPE)i); + ULONG propertyValue = 0; + char propertyName[256]; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-size", path)); + + // Sample driver uses this proeprty to determine whether to use PathDescriptor2 or PathDescriptor + NTSTATUS tempStatus = Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue); + if (!NT_SUCCESS(tempStatus)) + { + // This special stream is either not supported or does not use PathDescriptor2 + continue; + } + + pPathDesc2 = (PSDCA_PATH_DESCRIPTORS2)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + propertyValue, + DRIVER_TAG); + if (pPathDesc2 == nullptr) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + + auto cleanup2 = scope_exit([&pPathDesc2]() + { + if (pPathDesc2 != NULL) + { + ExFreePool(pPathDesc2); + pPathDesc2 = NULL; + } + }); + + pPathDesc2->Size = propertyValue; + pPathDesc2->Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + pPathDesc2->SdcaPath = path; + + // Since we found one specialstream property, all others are required to be present + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-endpoint-id", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->EndpointId = propertyValue; + + pPathDesc2->SpecialPathFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-specialpathformat-channels", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->SpecialPathFormat.Format.nChannels = (WORD)propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-specialpathformat-bits-per-sample", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->SpecialPathFormat.Format.wBitsPerSample = (WORD)propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-specialpathformat-samples-per-sec", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->SpecialPathFormat.Format.nSamplesPerSec = propertyValue; + pPathDesc2->SpecialPathFormat.Format.nBlockAlign = pPathDesc2->SpecialPathFormat.Format.nChannels * pPathDesc2->SpecialPathFormat.Format.wBitsPerSample; + pPathDesc2->SpecialPathFormat.Format.nAvgBytesPerSec = pPathDesc2->SpecialPathFormat.Format.nSamplesPerSec * pPathDesc2->SpecialPathFormat.Format.nBlockAlign; + pPathDesc2->SpecialPathFormat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-specialpathformat-valid-bits-per-sample", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->SpecialPathFormat.Samples.wValidBitsPerSample = (WORD)propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-specialpathformat-channel-mask", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->SpecialPathFormat.dwChannelMask = propertyValue; + pPathDesc2->SpecialPathFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-count", path)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->DescriptorCount = propertyValue; + + for (ULONG j = 0; j < pPathDesc2->DescriptorCount; j++) + { + pPathDesc2->Descriptor[j].Size = sizeof(pPathDesc2->Descriptor[0]); + pPathDesc2->Descriptor[j].Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + + + // In this sample, we are getting the function informaiton id from audio composition data, however, this id is + // generated at runtime so the real drivers would have information like function number, peripheral id etc. in + // its composition data and then use that to map it to a function information id by querying down stream circuit. + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-func-info-id", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].FunctionInformationId = propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-terminal-id", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].TerminalEntityId = propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-dp-map", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].DataPortMap = propertyValue; + + // DataPortMap indicates which DPIndex entries are used, in this sample we'll only use + // a single data port and that will be DPIndex_A. + pPathDesc2->Descriptor[j].DataPortConfig[0].Size = sizeof(pPathDesc2->Descriptor[0].DataPortConfig); + pPathDesc2->Descriptor[j].DataPortConfig[0].EndpointId = pPathDesc2->EndpointId; + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-dp-index-0x0-dp-number", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].DataPortConfig[0].DataPortNumber = propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-dp-index-0x0-dp-modes", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].DataPortConfig[0].Modes = propertyValue; + + RETURN_NTSTATUS_IF_FAILED(RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-specialstream-0x%x-desc-0x%x-dp-index-0x0-dp-channel-mask", path, j)); + RETURN_NTSTATUS_IF_FAILED(Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &propertyValue)); + pPathDesc2->Descriptor[j].DataPortConfig[0].ChannelMask = propertyValue; + } + + // Now save it to circuitCtx + circuitCtx->SpecialStreamPathDescriptors2[i] = pPathDesc2; + cleanup2.release(); + } + +exit: + return status; +} + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ ULONG BridgeDataPortNumber, + _In_ ULONG BridgeEndpointId, + _In_opt_ PSDCA_PATH_DESCRIPTORS2 PathDescriptors, + _In_ BOOL Render +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId); + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DataPortNumber); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + attributes.ParentObject = Pin; + + ACX_OBJECTBAG_CONFIG objBagCfg; + ACXOBJECTBAG objBag = NULL; + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Circuit; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag)); + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &TestUI4, _DSP_STREAM_PROPERTY_UI4_VALUE)); + + // EndpointId, DataPortNumber, and DPNo included for backwards compatibility. + // If SdcaPropertyPathDescriptors2 is included in the object bag, these will be ignored. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &EndpointId, BridgeEndpointId)); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &DataPortNumber, BridgeDataPortNumber)); + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DPNo); + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(objBag, &DPNo, BridgeDataPortNumber)); + + if (PathDescriptors && PathDescriptors->Size >= sizeof(SDCA_PATH_DESCRIPTORS2)) + { + // For uniform aggregated devices and non-aggregated devices, we can save the SdcaPropertyPathDescriptors2 + // now to the stream bridge. + + // If the aggregated devices have different configurations (such as a different Channel Mask) the + // SdcaPropertyPathDescriptors2 should be added to the stream bridge when the pin is connected, since the + // FunctionInformationId is determined at run time based on the order that the aggregated devices are discovered. + + // Apply the EndpointID to the PathDescriptors structures + PathDescriptors->EndpointId = BridgeEndpointId; + + // The PathDescriptors->Descriptor[n].DataPortConfig[m].EndpointId value is ignored + + WDFMEMORY pathDescriptorsMemory; + RETURN_NTSTATUS_IF_FAILED(WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES, PathDescriptors, PathDescriptors->Size, &pathDescriptorsMemory)); + auto memory_free = scope_exit([&pathDescriptorsMemory]() + { + WdfObjectDelete(pathDescriptorsMemory); + pathDescriptorsMemory = nullptr; + }); + + // For sample simplicity we always add the path descriptors here. + // If the EvtPinConnected discovers connected aggregated audio functions it will overwrite this. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddBlob(objBag, &SdcaPropertyPathDescriptors2, pathDescriptorsMemory)); + } + + // Save the Object Bag that's being assigned to the stream bridge + // This will be updated at Pin Connect time if the connected endpoint is aggregated and uses + // different data ports for each of the aggregated audio functions + // The AcxObjectBag's lifetime is tied to the Circuit, so the Pin will be able to access it + // for the Pin's entire lifetime. + PinCtx->HostStreamObjBag = objBag; + + // + // Add a stream BRIDGE. + // + PCGUID inModes[] = + { + &AUDIO_SIGNALPROCESSINGMODE_RAW, + &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + }; + + if (Render) { + StreamCfg.InModesCount = SIZEOF_ARRAY(inModes); + StreamCfg.InModes = inModes; + } + + // Do not specify InModes for capture - this will prevent the ACX framework from adding created streams to this stream + // bridge automatically. We want to add the stream bridges manually since we don't want KWS streams added. + StreamCfg.OutMode = &AUDIO_SIGNALPROCESSINGMODE_RAW; + StreamCfg.OutStreamVarArguments = objBag; + + // Uncomment this line to reverse the change-state sequence notifications. + //streamCfg.Flags |= AcxStreamBridgeInvertChangeStateSequence; + + ACXSTREAMBRIDGE streamBridge = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeCreate(Circuit, &attributes, &StreamCfg, &streamBridge)); + + if (!Render) { + PinCtx->HostStreamBridge = streamBridge; + } + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddStreamBridges(Pin, &streamBridge, 1)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ConnectCaptureCircuitElements( + _In_ ULONG ElementCount, + _In_reads_(ElementCount) ACXELEMENT* Elements, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // connection between each element, plus the connection to the circuit, + // and an extra connection for the kws pin. + const int numElements = 3; + const int numConnections = numElements + 2; + + // + // Explicitly connect the circuit/elements. Note that driver doens't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for devices. + // + // circuit.pin[default_sink] -> 1st element.pin[default_in] + // 1st element.pin[default_out] -> 2nd element.pin[default_in] + // 2nd element.pin[default_out] -> circuit.pin[default_source] + // + + ACX_CONNECTION connections[numConnections]; + ACX_CONNECTION_INIT(&connections[0], Circuit, Elements[0]); + + ACX_CONNECTION_INIT(&connections[1], Elements[0], Elements[ElementCount-2]); + ACX_CONNECTION_INIT(&connections[2], Elements[ElementCount-2], Elements[ElementCount-1]); + ACX_CONNECTION_INIT(&connections[3], Elements[ElementCount-1], Circuit); + ACX_CONNECTION_INIT(&connections[4], Elements[ElementCount-1], Circuit); + connections[4].ToPin.Id = 1; + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections))); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Explicitly connect the circuit/elements. Note that driver doesn't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both render and capture devices. + // + // Circuit layout + // ----------------------------------------- + // | | + // | -------------------- | + // Host -0->|-----1->| |-0-------->|-3-> Bridge Pin + // | | Audio Engine | | + // Offload -1->|-----2->| Node |-3--| | + // | |------------------| | | + // | | | + // Loopback <-2-|<------------------------------ | | + // | | + // | | + // |---------------------------------------| + // + + ACX_CONNECTION connections[4]; + + ACX_CONNECTION_INIT(&connections[0], Circuit, AudioEngineElement); + connections[0].FromPin.Id = DspPinTypeHost; + connections[0].ToPin.Id = 1; + + ACX_CONNECTION_INIT(&connections[1], Circuit, AudioEngineElement); + connections[1].FromPin.Id = DspPinTypeOffload; + connections[1].ToPin.Id = 2; + + ACX_CONNECTION_INIT(&connections[2], AudioEngineElement, Circuit); + connections[2].ToPin.Id = DspPinTypeLoopback; + connections[2].FromPin.Id = 3; + + ACX_CONNECTION_INIT(&connections[3], AudioEngineElement, Circuit); + connections[3].ToPin.Id = DspPinTypeBridge; + connections[3].FromPin.Id = 0; + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections))); + + return status; + +} + +PAGED_CODE_SEG +NTSTATUS CreateAudioEngine( + _In_ ACXCIRCUIT Circuit, + _In_reads_(DspPinType_Count) ACXPIN* Pins, + _Out_ ACXAUDIOENGINE* AudioEngineElement +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ///////////////////////////////////////////////////////// + // + // Create two elements to handle volume and mute for the audioengine + // element + + // Mute + ACX_MUTE_CALLBACKS muteCallbacks; + ACX_MUTE_CALLBACKS_INIT(&muteCallbacks); + muteCallbacks.EvtAcxMuteAssignState = DspR_EvtMuteAssignState; + muteCallbacks.EvtAcxMuteRetrieveState = DspR_EvtMuteRetrieveState; + + ACX_MUTE_CONFIG muteCfg; + ACX_MUTE_CONFIG_INIT(&muteCfg); + muteCfg.ChannelsCount = MAX_CHANNELS; + muteCfg.Name = &KSAUDFNAME_WAVE_MUTE; + muteCfg.Callbacks = &muteCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_MUTE_ELEMENT_CONTEXT); + attributes.ParentObject = Circuit; + + ACXMUTE muteElement; + RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(Circuit, &attributes, &muteCfg, &muteElement)); + + // Volume + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxRampedVolumeAssignLevel = DspR_EvtRampedVolumeAssignLevel; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = DspR_EvtVolumeRetrieveLevel; + + ACX_VOLUME_CONFIG volumeCfg; + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Name = &KSAUDFNAME_VOLUME_CONTROL; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = Circuit; + + ACXVOLUME volumeElement; + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(Circuit, &attributes, &volumeCfg, &volumeElement)); + + // + // Create peakmeter element for Audio engine + // + ACX_PEAKMETER_CALLBACKS peakmeterCallbacks; + ACX_PEAKMETER_CALLBACKS_INIT(&peakmeterCallbacks); + peakmeterCallbacks.EvtAcxPeakMeterRetrieveLevel = DspR_EvtPeakMeterRetrieveLevelCallback; + + ACX_PEAKMETER_CONFIG peakmeterCfg; + ACX_PEAKMETER_CONFIG_INIT(&peakmeterCfg); + peakmeterCfg.ChannelsCount = MAX_CHANNELS; + peakmeterCfg.Minimum = PEAKMETER_MINIMUM; + peakmeterCfg.Maximum = PEAKMETER_MAXIMUM; + peakmeterCfg.SteppingDelta = PEAKMETER_STEPPING_DELTA; + peakmeterCfg.Callbacks = &peakmeterCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PEAKMETER_ELEMENT_CONTEXT); + attributes.ParentObject = Circuit; + + ACXPEAKMETER peakmeterElement; + RETURN_NTSTATUS_IF_FAILED(AcxPeakMeterCreate(Circuit, &attributes, &peakmeterCfg, &peakmeterElement)); + ASSERT(peakmeterElement != NULL); + + PDSP_PEAKMETER_ELEMENT_CONTEXT peakmeterCtx; + peakmeterCtx = GetDspPeakMeterElementContext(peakmeterElement); + ASSERT(peakmeterCtx); + peakmeterCtx->peakMeter = GetDspCircuitContext(Circuit)->peakMeter; + + GetDspCircuitContext(Circuit)->PeakMeterElement = peakmeterElement; + + // + // Create Audio Engine + // + ACX_AUDIOENGINE_CALLBACKS audioEngineCallbacks; + ACX_AUDIOENGINE_CALLBACKS_INIT(&audioEngineCallbacks); + audioEngineCallbacks.EvtAcxAudioEngineRetrieveBufferSizeLimits = DspR_EvtAcxAudioEngineRetrieveBufferSizeLimits; + audioEngineCallbacks.EvtAcxAudioEngineAssignEffectsState = DspR_EvtAcxAudioEngineAssignEffectsState; + audioEngineCallbacks.EvtAcxAudioEngineRetrieveEffectsState = DspR_EvtAcxAudioEngineRetrieveEffectsState; + audioEngineCallbacks.EvtAcxAudioEngineRetrieveEngineMixFormat = DspR_EvtAcxAudioEngineRetrieveEngineMixFormat; + audioEngineCallbacks.EvtAcxAudioEngineAssignEngineDeviceFormat = DspR_EvtAcxAudioEngineAssignEngineDeviceFormat; + + ACX_AUDIOENGINE_CONFIG audioEngineCfg; + ACX_AUDIOENGINE_CONFIG_INIT(&audioEngineCfg); + audioEngineCfg.HostPin = Pins[DspPinTypeHost]; + audioEngineCfg.OffloadPin = Pins[DspPinTypeOffload]; + audioEngineCfg.LoopbackPin = Pins[DspPinTypeLoopback]; + audioEngineCfg.VolumeElement = volumeElement; + audioEngineCfg.MuteElement = muteElement; + audioEngineCfg.PeakMeterElement = peakmeterElement; + audioEngineCfg.Callbacks = &audioEngineCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ENGINE_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioEngineCreate(Circuit, &attributes, &audioEngineCfg, AudioEngineElement)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SendProperty( + _In_ WDFOBJECT AcxTarget, + _Inout_ PACX_REQUEST_PARAMETERS PropertyParameters, + _Out_opt_ PULONG_PTR Information +) +{ + PAGED_CODE(); + + if (Information) + { + *Information = 0; + } + + // + // First step: Determine the WDFIOTARGET to which the property request will be sent + // + WDFIOTARGET ioTarget = nullptr; + if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypePin) + { + ioTarget = AcxTargetPinGetWdfIoTarget((ACXTARGETPIN)AcxTarget); + } + else if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypeElement) + { + ioTarget = AcxTargetElementGetWdfIoTarget((ACXTARGETELEMENT)AcxTarget); + } + else if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypeCircuit) + { + ioTarget = AcxTargetCircuitGetWdfIoTarget((ACXTARGETCIRCUIT)AcxTarget); + } + else + { + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Create the request + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = AcxTarget; + + WDFREQUEST request; + RETURN_NTSTATUS_IF_FAILED(WdfRequestCreate(&attributes, ioTarget, &request)); + auto request_free = scope_exit([&request]() + { + WdfObjectDelete(request); + request = nullptr; + }); + + // + // ACX framework will format the request properly depending on the type of the target + // + if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypePin) + { + RETURN_NTSTATUS_IF_FAILED(AcxTargetPinFormatRequestForProperty((ACXTARGETPIN)AcxTarget, request, PropertyParameters)); + } + else if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypeElement) + { + RETURN_NTSTATUS_IF_FAILED(AcxTargetElementFormatRequestForProperty((ACXTARGETELEMENT)AcxTarget, request, PropertyParameters)); + } + else if (PropertyParameters->Parameters.Property.ItemType == AcxItemTypeCircuit) + { + RETURN_NTSTATUS_IF_FAILED(AcxTargetCircuitFormatRequestForProperty((ACXTARGETCIRCUIT)AcxTarget, request, PropertyParameters)); + } + + // + // Send the request synchronously, with a timeout + // + WDF_REQUEST_SEND_OPTIONS sendOptions; + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(REQUEST_TIMEOUT_SECONDS)); + + if (!WdfRequestSend(request, ioTarget, &sendOptions)) + { + // + // The framework failed to send the request. + // + RETURN_NTSTATUS_IF_FAILED(WdfRequestGetStatus(request)); + } + + // + // The request was successfully delivered and handled. The status will be based on the target's handling + // + if (Information) + { + *Information = WdfRequestGetInformation(request); + } + + return WdfRequestGetStatus(request); +} + +// Nonpaged, since this will be called in power up situations +#pragma code_seg() +VOID CircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This Circuit Request Preprocess routine will forward any Volume + or Mute requests to the appropriate downstream circuit, if we've + discovered a downstream circuit that handles Volume and Mute + +--*/ +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ACX_REQUEST_PARAMETERS targetParams; + PDSP_CIRCUIT_CONTEXT circuitCtx; + ACXELEMENT element; + ULONG_PTR information = 0; + ACXTARGETELEMENT targetElement = nullptr; + GUID propertySet; + ULONG propertyId; + BOOLEAN isMute = FALSE; + BOOLEAN isVolume = FALSE; + + // Preprocess will be called very frequently. Don't trace enter/exit. + //DrvLogEnter(g_SDCAVDspLog); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + propertySet = params.Parameters.Property.Set; + propertyId = params.Parameters.Property.Id; + circuitCtx = GetDspCircuitContext(Object); + + if (circuitCtx == nullptr || + params.Parameters.Property.ItemType != AcxItemTypeElement) + { + // We only handle requests for our render circuit (which must have our context) + // We only forward element requests to the child paths + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + if (IsEqualGUID(propertySet, KSPROPSETID_Audio) && propertyId == KSPROPERTY_AUDIO_VOLUMELEVEL) + { + isVolume = TRUE; + } + else if (IsEqualGUID(propertySet, KSPROPSETID_Audio) && propertyId == KSPROPERTY_AUDIO_MUTE) + { + isMute = TRUE; + } + // Do not forward KSPROPERTY_AUDIOENGINE_VOLUMELEVEL - that is only valid for a stream property. + + if (!isVolume && !isMute) + { + // Only handle Volume and Mute requests + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + element = AcxCircuitGetElementById((ACXCIRCUIT)Object, params.Parameters.Property.ItemId); + if (!element) + { + // We only handle requests for the volume or mute elements, and this isn't an element + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + if (isVolume) + { + targetElement = circuitCtx->TargetVolumeHandler; + } + else if (isMute) + { + targetElement = circuitCtx->TargetMuteHandler; + } + + if (targetElement == nullptr) + { + // We only handle requests for the volume or mute elements if we have a target. + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + if (isVolume && (GetDspVolumeElementContext(element) == nullptr && GetDspEngineContext(element) == nullptr)) + { + // Volume request that isn't for our volume or audioengine element? + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + if (isMute && (GetDspMuteElementContext(element) == nullptr && GetDspEngineContext(element) == nullptr)) + { + // Mute request that isn't for our mute or audioengine element? + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + return; + } + + propertySet = params.Parameters.Property.Set; + propertyId = params.Parameters.Property.Id; + + ACX_REQUEST_PARAMETERS_INIT_PROPERTY(&targetParams, + propertySet, + propertyId, + params.Parameters.Property.Verb, + params.Parameters.Property.ItemType, + AcxTargetElementGetId(targetElement), + params.Parameters.Property.Control, + params.Parameters.Property.ControlCb, + params.Parameters.Property.Value, + params.Parameters.Property.ValueCb); + + status = SendProperty(targetElement, &targetParams, &information); + + WdfRequestCompleteWithInformation(Request, status, information); +} + +PAGED_CODE_SEG +NTSTATUS CreateTargetCircuit( + _In_ ACXCIRCUIT Circuit, + _In_ PKSPIN_PHYSICALCONNECTION Connection, + _In_ ULONG ConnectionSize, + _Out_ ACXTARGETCIRCUIT * TargetCircuit +) +{ + PAGED_CODE(); + + // We have the physical connection. Create a target circuit for it. + size_t symbolicLinkSize; + // Size of the string is no more than the total size of the value returned, less the size of the physicalconnection struct, + // plus the first character of the link (which is included in the physicalconnection struct) + symbolicLinkSize = ConnectionSize - sizeof(KSPIN_PHYSICALCONNECTION) + sizeof(WCHAR); + if (symbolicLinkSize > USHORT_MAX) + { + // Symbolic Link has to fit in UNICODE_STRING which uses USHORT to hold Length/MaximumLength + RETURN_NTSTATUS_MSG(STATUS_UNSUCCESSFUL, L"Physical connection too large for unicode_string %lld", symbolicLinkSize); + } + + UNICODE_STRING symbolicLink{ 0 }; + symbolicLink.MaximumLength = (USHORT)symbolicLinkSize; + symbolicLink.Buffer = Connection->SymbolicLinkName; + // preload the length + (void)RtlStringCbLengthW(symbolicLink.Buffer, symbolicLink.MaximumLength, &symbolicLinkSize); + symbolicLink.Length = (USHORT)symbolicLinkSize; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Circuit; + + WDFSTRING link; + RETURN_NTSTATUS_IF_FAILED(WdfStringCreate(&symbolicLink, &attributes, &link)); + auto link_free = scope_exit([&link]() + { + if (link) + { + WdfObjectDelete(link); + link = nullptr; + } + }); + + ACX_TARGET_CIRCUIT_CONFIG targetCktCfg; + ACX_TARGET_CIRCUIT_CONFIG_INIT(&targetCktCfg); + targetCktCfg.SymbolicLinkName = link; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxTargetCircuitCreate(AcxCircuitGetWdfDevice(Circuit), &attributes, &targetCktCfg, TargetCircuit)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS FindDownstreamVolumeMute( + _In_ ACXCIRCUIT Circuit, + _In_ ACXTARGETCIRCUIT TargetCircuit +) +{ + NTSTATUS status; + PDSP_CIRCUIT_CONTEXT circuitCtx; + ACX_REQUEST_PARAMETERS params; + + PAGED_CODE(); + + circuitCtx = GetDspCircuitContext(Circuit); + + // + // Note on behavior: This search algorithm will select the last Volume and Mute elements that are both + // present in the same circuit in the Endpoint Path. + // This logic could be updated to select the last Volume and Mute elements, or the first or last + // Volume or the first or last Mute element. + // + + // + // First look through target's pins to determine if there's another circuit downstream. + // If there is, we'll look at that circuit for volume/mute. + // + for (ULONG pinIndex = 0; pinIndex < AcxTargetCircuitGetPinsCount(TargetCircuit); ++pinIndex) + { + ACXTARGETPIN targetPin = AcxTargetCircuitGetTargetPin(TargetCircuit, pinIndex); + ULONG targetPinFlow = 0; + ACX_REQUEST_PARAMETERS_INIT_PROPERTY(¶ms, + KSPROPSETID_Pin, + KSPROPERTY_PIN_DATAFLOW, + AcxPropertyVerbGet, + AcxItemTypePin, + AcxTargetPinGetId(targetPin), + nullptr, 0, + &targetPinFlow, + sizeof(targetPinFlow)); + + RETURN_NTSTATUS_IF_FAILED(SendProperty(targetPin, ¶ms, nullptr)); + + // + // Searching for the downstream pins. For Render, these are the dataflow out pins + // + if (circuitCtx->IsRenderCircuit && targetPinFlow != KSPIN_DATAFLOW_OUT) + { + continue; + } + else if (!circuitCtx->IsRenderCircuit && targetPinFlow != KSPIN_DATAFLOW_IN) + { + continue; + } + + // Get the target pin's physical connection. We'll do this twice: first to get size and allocate, second to get the connection + PKSPIN_PHYSICALCONNECTION pinConnection = nullptr; + auto connection_free = scope_exit([&pinConnection]() + { + if (pinConnection) + { + ExFreePool(pinConnection); + pinConnection = nullptr; + } + }); + + ULONG pinConnectionSize = 0; + ULONG_PTR info = 0; + for (ULONG i = 0; i < 2; ++i) + { + ACX_REQUEST_PARAMETERS_INIT_PROPERTY(¶ms, + KSPROPSETID_Pin, + KSPROPERTY_PIN_PHYSICALCONNECTION, + AcxPropertyVerbGet, + AcxItemTypePin, + AcxTargetPinGetId(targetPin), + nullptr, 0, + pinConnection, + pinConnectionSize); + + status = SendProperty(targetPin, ¶ms, &info); + + if (status == STATUS_BUFFER_OVERFLOW) + { + // Pin connection already allocated, so how did this fail? + RETURN_NTSTATUS_IF_TRUE(pinConnection != nullptr, status); + + pinConnectionSize = (ULONG)info; + pinConnection = (PKSPIN_PHYSICALCONNECTION)ExAllocatePool2(POOL_FLAG_NON_PAGED, pinConnectionSize, DRIVER_TAG); + // RETURN_NTSTATUS_IF_NULL_ALLOC causes compile errors + RETURN_NTSTATUS_IF_TRUE(pinConnection == nullptr, STATUS_INSUFFICIENT_RESOURCES); + } + else if (!NT_SUCCESS(status)) + { + // There are no more connected circuits. Continue with processing this circuit. + break; + } + } + + if (!NT_SUCCESS(status)) + { + // There are no more connected circuits. Continue handling this circuit. + break; + } + + ACXTARGETCIRCUIT nextTargetCircuit; + RETURN_NTSTATUS_IF_FAILED(CreateTargetCircuit(Circuit, pinConnection, pinConnectionSize, &nextTargetCircuit)); + auto circuit_free = scope_exit([&nextTargetCircuit]() + { + if (nextTargetCircuit) + { + WdfObjectDelete(nextTargetCircuit); + nextTargetCircuit = nullptr; + } + }); + + RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(FindDownstreamVolumeMute(Circuit, nextTargetCircuit), STATUS_NOT_FOUND); + if (circuitCtx->TargetVolumeMuteCircuit == nextTargetCircuit) + { + circuitCtx->TargetCircuitToDelete = nextTargetCircuit; + + // The nextTargetCircuit is the owner of the volume/mute target elements. + // We will delete it when the pin is disconnected. + circuit_free.release(); + + // We found volume/mute. Return. + return STATUS_SUCCESS; + } + + // There's only one downstream pin on the current targetcircuit, and we just processed it. + break; + } + + // + // Search the target circuit for a volume or mute element. + // This sample code doesn't support downstream audioengine elements. + // + for (ULONG elementIndex = 0; elementIndex < AcxTargetCircuitGetElementsCount(TargetCircuit); ++elementIndex) + { + ACXTARGETELEMENT targetElement = AcxTargetCircuitGetTargetElement(TargetCircuit, elementIndex); + GUID elementType = AcxTargetElementGetType(targetElement); + + if (IsEqualGUID(elementType, KSNODETYPE_VOLUME) && + circuitCtx->TargetVolumeHandler == nullptr) + { + // Found Volume + circuitCtx->TargetVolumeHandler = targetElement; + } + if (IsEqualGUID(elementType, KSNODETYPE_MUTE) && + circuitCtx->TargetMuteHandler == nullptr) + { + // Found Mute + circuitCtx->TargetMuteHandler = targetElement; + } + } + + if (circuitCtx->TargetVolumeHandler && circuitCtx->TargetMuteHandler) + { + circuitCtx->TargetVolumeMuteCircuit = TargetCircuit; + return STATUS_SUCCESS; + } + + // + // If we only found one of volume or mute, keep searching for both + // + if (circuitCtx->TargetVolumeHandler || circuitCtx->TargetMuteHandler) + { + circuitCtx->TargetMuteHandler = circuitCtx->TargetVolumeHandler = nullptr; + } + + return STATUS_NOT_FOUND; +} + +PAGED_CODE_SEG +NTSTATUS +ReplicateFormatsForAudioEngine( + _In_ ACXAUDIOENGINE AudioEngine, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +) +{ + PAGED_CODE(); + + ACXTARGETPIN targetPin; + targetPin = AcxTargetCircuitGetTargetPin(TargetCircuit, TargetPinId); + if (!targetPin) + { + RETURN_NTSTATUS(STATUS_UNSUCCESSFUL); + } + + ACXDATAFORMATLIST targetFormatList; + // We expect at least Raw format in SDCA downstream circuits + RETURN_NTSTATUS_IF_FAILED(AcxTargetPinRetrieveModeDataFormatList(targetPin, &AUDIO_SIGNALPROCESSINGMODE_RAW, &targetFormatList)); + + ACXDATAFORMATLIST localFormatList = AcxAudioEngineGetDeviceFormatList(AudioEngine); + + RETURN_NTSTATUS_IF_FAILED(SdcaVad_ClearDataFormatList(localFormatList)); + + ULONG formatCount = 0; + RETURN_NTSTATUS_IF_FAILED(SdcaVad_CopyFormats(targetFormatList, localFormatList, &formatCount)); + + if (formatCount == 0) + { + RETURN_NTSTATUS(STATUS_NO_MATCH); + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +ReplicateFormatsForPin( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +) +{ + PAGED_CODE(); + + ACXTARGETPIN targetPin; + targetPin = AcxTargetCircuitGetTargetPin(TargetCircuit, TargetPinId); + if (!targetPin) + { + RETURN_NTSTATUS(STATUS_UNSUCCESSFUL); + } + + // Don't delete the target pin - it will be cleaned up when the target circuit is cleaned up by ACX + + GUID targetModes[] = + { + AUDIO_SIGNALPROCESSINGMODE_RAW, + AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, + AUDIO_SIGNALPROCESSINGMODE_SPEECH + }; + + ULONG totalFormats = 0; + + for (ULONG modeIdx = 0; modeIdx < ARRAYSIZE(targetModes); ++modeIdx) + { + ACXDATAFORMATLIST targetFormatList; + ACXDATAFORMATLIST localFormatList = nullptr; + + NTSTATUS status = AcxTargetPinRetrieveModeDataFormatList(targetPin, targetModes + modeIdx, &targetFormatList); + if (!NT_SUCCESS(status)) + { + // If the downstream pin doesn't support any formats for this mode, make sure we clear out our pin's + // formats for this mode as well. + if (modeIdx == 0) + { + localFormatList = AcxPinGetRawDataFormatList(Pin); + } + else + { + // Ignore the status + AcxPinRetrieveModeDataFormatList(Pin, targetModes + modeIdx, &localFormatList); + } + if (localFormatList) + { + RETURN_NTSTATUS_IF_FAILED(SdcaVad_ClearDataFormatList(localFormatList)); + } + continue; + } + + RETURN_NTSTATUS_IF_FAILED(SdcaVad_RetrieveOrCreateDataFormatList(Pin, targetModes + modeIdx, &localFormatList)); + + RETURN_NTSTATUS_IF_FAILED(SdcaVad_ClearDataFormatList(localFormatList)); + + ULONG formatCount = 0; + RETURN_NTSTATUS_IF_FAILED(SdcaVad_CopyFormats(targetFormatList, localFormatList, &formatCount)); + + totalFormats += formatCount; + } + + if (totalFormats == 0) + { + return STATUS_NO_MATCH; + } + + return STATUS_SUCCESS; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.h new file mode 100644 index 00000000..9324e7eb --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/CircuitHelper.h @@ -0,0 +1,135 @@ +/*++ + + 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: + + CircuitHelper.h + +Abstract: + + This module contains helper functions for render.cpp and capture.cpp files. + +Environment: + + Kernel mode + +--*/ + +#include "AcpiReader.h" + +using namespace ACPIREADER; + +PAGED_CODE_SEG +NTSTATUS CreateCaptureCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateRenderCircuit( + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ UNICODE_STRING CircuitName, + _In_ WDFDEVICE Device, + _Out_ ACXCIRCUIT* Circuit +); + +PAGED_CODE_SEG +NTSTATUS AllocateFormat( + _In_ KSDATAFORMAT_WAVEFORMATEXTENSIBLE WaveFormat, + _In_ ACXCIRCUIT Circuit, + _In_ WDFDEVICE Device, + _Out_ ACXDATAFORMAT* Format +); + +PAGED_CODE_SEG +NTSTATUS CreatePin( + _In_ ACX_PIN_TYPE PinType, + _In_ ACXCIRCUIT Circuit, + _In_ ACX_PIN_COMMUNICATION Communication, + _In_ const GUID* Category, + _In_ ACX_PIN_CALLBACKS* PinCallbacks, + _In_ ULONG PinStreamCount, + _In_ bool Mic, + _Out_ ACXPIN* Pin +); + +PAGED_CODE_SEG +NTSTATUS RetrieveProperties( + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _In_ PULONG EndpointID +); + +PAGED_CODE_SEG +NTSTATUS +DetermineSpecialStreamDetailsFromVendorProperties( + _In_ ACXCIRCUIT Circuit, + _In_ AcpiReader * Acpi, + _In_ HANDLE CircuitPropertiesHandle +); + +PAGED_CODE_SEG +NTSTATUS CreateStreamBridge( + _In_ ACX_STREAM_BRIDGE_CONFIG StreamCfg, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ DSP_PIN_CONTEXT* PinCtx, + _In_ ULONG BridgeDataPortNumber, + _In_ ULONG BridgeEndpointId, + _In_opt_ PSDCA_PATH_DESCRIPTORS2 PathDescriptors, + _In_ BOOL Render +); + +PAGED_CODE_SEG +NTSTATUS ConnectCaptureCircuitElements( + _In_ ULONG ElementCount, + _In_reads_(ElementCount) ACXELEMENT* Elements, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS ConnectRenderCircuitElements( + _In_ ACXAUDIOENGINE AudioEngineElement, + _In_ ACXCIRCUIT Circuit +); + +PAGED_CODE_SEG +NTSTATUS CreateAudioEngine( + _In_ ACXCIRCUIT Circuit, + _In_reads_(DspPinType_Count) ACXPIN* Pins, + _Out_ ACXAUDIOENGINE* AudioEngineElement +); + +#pragma code_seg() +VOID CircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +); + +PAGED_CODE_SEG +NTSTATUS FindDownstreamVolumeMute( + _In_ ACXCIRCUIT Circuit, + _In_ ACXTARGETCIRCUIT TargetCircuit +); + +PAGED_CODE_SEG +NTSTATUS +ReplicateFormatsForAudioEngine( + _In_ ACXAUDIOENGINE AudioEngine, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +); + +PAGED_CODE_SEG +NTSTATUS +ReplicateFormatsForPin( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +); diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.cpp new file mode 100644 index 00000000..3611a2c1 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.cpp @@ -0,0 +1,1053 @@ +/*++ + +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: + + KeywordDetector.cpp + +Abstract: + + Sample keyword detector management. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" + +#include "KeywordDetector.h" + +#ifndef __INTELLISENSE__ +#include "KeywordDetector.tmh" +#endif + + +#pragma code_seg("PAGE") +CKeywordDetector::CKeywordDetector( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WAVEFORMATEXTENSIBLE *DetectionFormat +) + : + m_streamRunning(FALSE), + m_qpcStartCapture(0), + m_nLastQueuedPacket(-1), + m_SoundDetectorArmed1(FALSE), + m_SoundDetectorArmed2(FALSE), + m_SoundDetectorData1(0), + m_SoundDetectorData2(0), + m_ullKeywordStartTimestamp(0), + m_ullKeywordStopTimestamp(0), + m_Device(Device), + m_Circuit(Circuit), + m_Prepared(FALSE), + m_Suspended(FALSE), + m_dispatchThread(nullptr), + m_FunctionInformation(nullptr), + m_Initialized(FALSE) +{ + PAGED_CODE(); + DSP_CIRCUIT_CONTEXT *circuitCtx; + + memcpy(&(m_PrepareParams.DetectionFormat), DetectionFormat, sizeof(WAVEFORMATEXTENSIBLE)); + circuitCtx = GetDspCircuitContext(m_Circuit); + m_PrepareParams.EndpointId = circuitCtx->EndpointId; + + // Assume streaming (bypass) mode + m_PrepareParams.VadMode = VadModeStreaming; + + KeInitializeEvent(&(m_Events.Suspend), SynchronizationEvent, FALSE); + KeInitializeEvent(&(m_Events.Resume), SynchronizationEvent, FALSE); + + // Initialize our pool of packets and the list structures + // The packet spin locks protect the producer/consumer relationship + // between the dpc routine and GetReadPacket + KeInitializeSpinLock(&m_PacketPoolSpinLock); + KeInitializeSpinLock(&m_PacketFifoSpinLock); + + // The buffering state spin lock protects the state variables + // shared between the arm/disarm and the dpc routine + KeInitializeSpinLock(&m_BufferingStateSpinLock); + + // current state is disarmed + // reset fifo and buffering state + UpdateBufferingState(); +} + +#pragma code_seg("PAGE") +CKeywordDetector::~CKeywordDetector() +{ + PAGED_CODE(); + + m_threadExitEvent.set(); + m_threadExitedEvent.wait(); + + if (m_FunctionInformation) + { + ExFreePool(m_FunctionInformation); + } + + m_Initialized = FALSE; +} + + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::Initialize() +{ + PAGED_CODE(); + HANDLE handle; + LARGE_INTEGER qpcFrequency; + + KeQueryPerformanceCounter(&qpcFrequency); + m_qpcFrequency = qpcFrequency.QuadPart; + + // TODO: currently ignoring the results of these calls as to + // not break anything (since they all currently fail) + + // Retrieve capabilities to know ivad/evad, and + // entity id's + RETURN_NTSTATUS_IF_FAILED(GetDeviceKwsCapabilityDescriptor(&m_CapabilityDescriptor)); + RETURN_NTSTATUS_IF_FAILED(GetDeviceFunctionInformation(&m_FunctionInformation)); + RETURN_NTSTATUS_IF_TRUE(0 == m_CapabilityDescriptor.DataPathsSupported, STATUS_NOT_SUPPORTED); + + RETURN_NTSTATUS_IF_FAILED(GetVadDescriptor(&m_VadDescriptor)); + RETURN_NTSTATUS_IF_FAILED(GetVadEntities(&m_VadEntities)); + + // create worker thread to handle suspended access + RETURN_NTSTATUS_IF_FAILED(PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, 0, 0, 0, CKeywordDetector::s_HandleNotifications, this)); + + auto scope_exit([&handle]() { + ZwClose(handle); + }); + + RETURN_NTSTATUS_IF_FAILED(ObReferenceObjectByHandleWithTag(handle, THREAD_ALL_ACCESS, nullptr, KernelMode, KEYWORDDETECTOR_POOLTAG, (PVOID*)&m_dispatchThread, nullptr)); + + // set notification events + RETURN_NTSTATUS_IF_FAILED(SetSuspendAccessEvent(&m_Events)); + + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +void CKeywordDetector::s_HandleNotifications(PVOID context) +{ + PAGED_CODE(); + auto kws = static_cast<CKeywordDetector*>(context); + kws->HandleNotifications(); +} + +_IRQL_requires_(PASSIVE_LEVEL) +void +CKeywordDetector::HandleNotifications() +{ + PAGED_CODE(); + NTSTATUS status{ STATUS_SUCCESS }; + PVOID waitObjects[] = { &m_Events.Suspend, &m_Events.Resume, m_threadExitEvent.get() }; + + // start with the even reset to indicate that the thread is running + m_threadExitedEvent.clear(); + while (true) + { + status = KeWaitForMultipleObjects(3, waitObjects, WaitAny, Executive, KernelMode, FALSE, nullptr, nullptr); + if (STATUS_WAIT_0 == status) + { + auto lock = m_csLock.acquire(); +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_Suspended = TRUE; +#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "wil::fast_mutex lacks required SAL annotation, lock is held") + UpdateVadStreamState(); + continue; + } + if (STATUS_WAIT_1 == status) + { + auto lock = m_csLock.acquire(); +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_Suspended = FALSE; +#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "wil::fast_mutex lacks required SAL annotation, lock is held") + UpdateVadStreamState(); + continue; + } + + else // consider as exit event + { + break; + } + } + m_threadExitedEvent.set(); + PsTerminateSystemThread(status); +} + + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ReadKeywordTimestampRegistry() +{ + PAGED_CODE(); + + 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"KeywordDetectorStartTimestamp", &m_ullKeywordStartTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStartTimestamp, sizeof(ULONGLONG) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"KeywordDetectorStopTimestamp", &m_ullKeywordStopTimestamp, (REG_QWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_QWORD, &m_ullKeywordStopTimestamp, sizeof(ULONGLONG) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + RtlInitUnicodeString(¶metersPath, 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); + +#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit") + parametersPath.Buffer = (PWCH)ExAllocatePool2(PagedPool, parametersPath.MaximumLength, KEYWORDDETECTOR_POOLTAG); + RETURN_NTSTATUS_IF_TRUE(parametersPath.Buffer == NULL, STATUS_INSUFFICIENT_RESOURCES); + auto parametersPath_free = scope_exit([¶metersPath]() { + PAGED_CODE(); + ExFreePool(parametersPath.Buffer); + }); + + RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); + RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + + RETURN_NTSTATUS_IF_FAILED(RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + parametersPath.Buffer, + ¶mTable[0], + NULL, + NULL + )); + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::ResetDetector(_In_ GUID eventId) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_TRUE(eventId != CONTOSO_KEYWORD1 && + eventId != CONTOSO_KEYWORD2 && + eventId != GUID_NULL, + STATUS_INVALID_PARAMETER); + + // Initialize detector on first use, which is going to be the + // initial reset of the detector. + if(!m_Initialized) + { + RETURN_NTSTATUS_IF_FAILED(Initialize()); + m_Initialized = TRUE; + } + + auto lock = m_csLock.acquire(); + + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = 0; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed1 = FALSE; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = 0; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed2 = FALSE; + } + else if(eventId == GUID_NULL) + { + // When DownloadDetectorData is called to set the pattern for multiple keywords + // at once, all keyword detectors must be reset. Also used during keyword detector + // initialization and cleanup to restore it back to initial state and power down. + m_SoundDetectorData1 = 0; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed1 = FALSE; + m_SoundDetectorData2 = 0; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed2 = FALSE; + } + +#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "wil::fast_mutex lacks required SAL annotation, lock is held") + RETURN_NTSTATUS_IF_FAILED(UpdateVadStreamState()); + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_TRUE(eventId != CONTOSO_KEYWORD1 && + eventId != CONTOSO_KEYWORD2 && + eventId != GUID_NULL, + STATUS_INVALID_PARAMETER); + + + // reset the detector for this event Id + ResetDetector(eventId); + + // In this example, the driver supports detection data + // set with a single call for both detectors, or each + // detector set individually. + if (eventId == CONTOSO_KEYWORD1) + { + m_SoundDetectorData1 = Data; + } + else if(eventId == CONTOSO_KEYWORD2) + { + m_SoundDetectorData2 = Data; + } + else if(eventId == GUID_NULL) + { + // in this simplified example "Data" is set on both detectors, + // however in a real system "Data" could be a data structure which + // contains different values for each detector. + m_SoundDetectorData1 = m_SoundDetectorData2 = Data; + } + + return STATUS_SUCCESS; +} + +// The following function is only applicable to single keyword detection systems, +// and assumes keyword detector #1. +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_TRUE(eventId != CONTOSO_KEYWORD1 && + eventId != CONTOSO_KEYWORD2 && + eventId != GUID_NULL, + STATUS_INVALID_PARAMETER); + + *Data = 0; + + if (eventId == CONTOSO_KEYWORD1) + { + *Data = m_SoundDetectorData1; + } + else if(eventId == CONTOSO_KEYWORD2) + { + *Data = m_SoundDetectorData2; + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStartTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStartTimestamp; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +ULONGLONG CKeywordDetector::GetStopTimestamp() +{ + PAGED_CODE(); + + return m_ullKeywordStopTimestamp; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm) +{ + PAGED_CODE(); + + BOOLEAN previousDetector1State = FALSE; + BOOLEAN previousDetector2State = FALSE; + + RETURN_NTSTATUS_IF_TRUE(eventId != CONTOSO_KEYWORD1 && + eventId != CONTOSO_KEYWORD2 && + eventId != GUID_NULL, + STATUS_INVALID_PARAMETER); + + // lock scope enter + { + auto lock = m_csLock.acquire(); + + // the previous state is "armed" if either detector is armed. + // this reflects the fact that both detectors are sharing the + // same stream. +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + previousDetector1State = m_SoundDetectorArmed1; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + previousDetector2State = m_SoundDetectorArmed2; + + auto revertOnFailure = scope_exit([&]() { + PAGED_CODE(); +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed1 = previousDetector1State; +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed2 = previousDetector2State; +#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "wil::fast_mutex lacks required SAL annotation, lock is held") + UpdateVadStreamState(); + }); + + if (eventId == CONTOSO_KEYWORD1) + { +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed1 = Arm; + } + else if(eventId == CONTOSO_KEYWORD2) + { +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + m_SoundDetectorArmed2 = Arm; + } + +#pragma prefast(suppress:__WARNING_CALLER_FAILING_TO_HOLD, "wil::fast_mutex lacks required SAL annotation, lock is held") + RETURN_NTSTATUS_IF_FAILED(UpdateVadStreamState()); + + revertOnFailure.release(); + } + + // Change buffering state if needed + UpdateBufferingState(); + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_TRUE(eventId != CONTOSO_KEYWORD1 && + eventId != CONTOSO_KEYWORD2 && + eventId != GUID_NULL, + STATUS_INVALID_PARAMETER); + + auto lock = m_csLock.acquire(); + + *Arm = FALSE; + + if (eventId == CONTOSO_KEYWORD1) + { +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + *Arm = m_SoundDetectorArmed1; + } + else if(eventId == CONTOSO_KEYWORD2) + { +#pragma prefast(suppress:__WARNING_NEED_NO_COMPETING_THREAD, "wil::fast_mutex lacks required SAL annotation, lock is held") + *Arm = m_SoundDetectorArmed2; + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Run() +{ + PAGED_CODE(); + m_streamRunning = TRUE; + UpdateBufferingState(); +} + +#pragma code_seg("PAGE") +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::Stop() +{ + PAGED_CODE(); + m_streamRunning = FALSE; + UpdateBufferingState(); +} + +#pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::UpdateBufferingState() +{ + BOOL armed = FALSE; + KIRQL irql = PASSIVE_LEVEL; + + { + auto lock = m_csLock.acquire(); +#pragma prefast(suppress:__WARNING_RACE_CONDITION, "wil::fast_mutex lacks required SAL annotation, lock is held") + armed = m_SoundDetectorArmed1 | m_SoundDetectorArmed2; + } + + // acquire buffering state spin lock to synchronize state changes with the running dpc routine + KeAcquireSpinLock(&m_BufferingStateSpinLock, &irql); + + if (armed || m_streamRunning) + { + // if we're armed or stream running, and not buffering, start buffering + // if m_qpcStartCapture is not 0, then it's already buffering + if (m_qpcStartCapture == 0) + { + m_qpcStartCapture = KeQueryPerformanceCounter(NULL).QuadPart; + } + } + else + { + // if we're disarmed and no stream running, reset buffering + m_qpcStartCapture = 0; + m_nLastQueuedPacket = (-1); + InitializeListHead(&m_PacketPoolHead); + InitializeListHead(&m_PacketFifoHead); + + for (int i = 0; i < ARRAYSIZE(m_PacketPool); i++) + { + InsertTailList(&m_PacketPoolHead, &m_PacketPool[i].ListEntry); + } + } + + KeReleaseSpinLock(&m_BufferingStateSpinLock, irql); + + return; +} + +#pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID CKeywordDetector::NotifyDetection() +{ + KIRQL irql = PASSIVE_LEVEL; + + // Because we are modifying shared buffer state to simulate a notification, + // we need to acquire the spin lock to synchronize this with the dpc routine + KeAcquireSpinLock(&m_BufferingStateSpinLock, &irql); + + // A detection will only happen if armed and the + // stream is already running. If there isn't a client + // running, then set the stream start time to align + // with this detection. + if (!m_streamRunning) + { + // the start capture time is now. + m_qpcStartCapture = KeQueryPerformanceCounter(NULL).QuadPart; + + // The following code is for testing purposes only. + // m_qpcFrequency is defined to be the number of ticks in 1 second. + // Use the stream start time (the current time retrieved in StartBufferStream) to + // mark when the keyword ended, and the start time minus 1 second worth of ticks + // to mark when the keyword started. Also, adjust the stream start time to align + // to this new keyword start time, so that the simulated stream contains the full keyword. + + m_ullKeywordStopTimestamp = m_qpcStartCapture; // stop time is the current time + m_qpcStartCapture = m_qpcStartCapture - m_qpcFrequency; // buffer start time is 1 second ago + m_ullKeywordStartTimestamp = m_qpcStartCapture; // buffer start time = keyword start time + + } + else + { + // The following code is for testing purposes only. + // If the stream is running, we cannot modify qpcStartCapture to be in + // the past, so instead make the keyword start & stop times fit within the + // time period that the keyword has been running. If it has been running + // for more than 1 second, then set the keyword start time to be 1 second back + // into the stream, as though we just figured out there was a keyword there. + // If it has been running less than one second, then the keyword size ends + // up being however long the stream has been running. + + LARGE_INTEGER qpc; + qpc = KeQueryPerformanceCounter(NULL); + + m_ullKeywordStopTimestamp = qpc.QuadPart; // stop time is the current time + + if (m_qpcStartCapture < (qpc.QuadPart - m_qpcFrequency)) + { + m_ullKeywordStartTimestamp = (qpc.QuadPart - m_qpcFrequency); + } + else + { + m_ullKeywordStartTimestamp = m_qpcStartCapture; + } + } + + KeReleaseSpinLock(&m_BufferingStateSpinLock, irql); + + return; +} + +#pragma code_seg() +_IRQL_requires_min_(DISPATCH_LEVEL) +VOID CKeywordDetector::DpcRoutine( + _In_ LONGLONG PerformanceCounter, + _In_ LONGLONG PerformanceFrequency, + _Out_ BOOLEAN *isRealtime, + _Out_ LONGLONG *NewPacketNumber, + _Out_ ULONGLONG *NewPerformanceCount) +{ + LONGLONG currentPacket; + LONGLONG packetsToQueue; + + KIRQL irql = PASSIVE_LEVEL; + + // used to synchronize buffering state variables with stream state changes, + // arming changes, etc. + KeAcquireSpinLock(&m_BufferingStateSpinLock, &irql); + + *isRealtime = FALSE; + *NewPacketNumber = 0; + *NewPerformanceCount = 0; + + // TODO: the timer only runs when the stream is open, but really for KWS it should be building up a collection of burst data + // in the queue from 1.5 sec before the trigger happens. Is there some way to simulate that behavior here? Without doing that, + // there isn't really a burst that happens, just a trickle because while the timestamps will be right, the queue won't contain + // anything until the timer fires at the normal rate. + + if (m_qpcStartCapture > 0) + { + currentPacket = (PerformanceCounter - m_qpcStartCapture) * (SamplesPerSecond / SamplesPerPacket) / PerformanceFrequency; + packetsToQueue = currentPacket - m_nLastQueuedPacket; + + // If the fifo is empty, and we're going to add something, then we are realtime + *isRealtime = IsListEmpty(&m_PacketFifoHead) && packetsToQueue > 0; + + *NewPacketNumber = m_nLastQueuedPacket+1; + *NewPerformanceCount = m_qpcStartCapture + (*NewPacketNumber * m_qpcFrequency * SamplesPerPacket / SamplesPerSecond); + + while (packetsToQueue > 0) + { + LIST_ENTRY* packetListEntry; + PACKET_ENTRY* packetEntry; + + do + { + packetListEntry = ExInterlockedRemoveHeadList(&m_PacketPoolHead, &m_PacketPoolSpinLock); + if (packetListEntry != NULL) break; + + // Pool is empty, no room to buffer more, an overrun is occurring. Drop and reuse the + // oldest packet from head of fifo. + + // Since the pool is empty, the fifo should be full. However, although unlikely, the + // driver might empty the fifo before this routine removes a packet. In that case, the + // pool should have packets available again. Therefore this is a retry loop. + packetListEntry = ExInterlockedRemoveHeadList(&m_PacketFifoHead, &m_PacketFifoSpinLock); + if (packetListEntry != NULL) break; + } while (TRUE); + + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + packetEntry->PacketNumber = ++m_nLastQueuedPacket; + packetEntry->QpcWhenSampled = m_qpcStartCapture + (packetEntry->PacketNumber * PerformanceFrequency * SamplesPerPacket / SamplesPerSecond); + + // TODO: this should really put something real in the buffer. Use the sine tone generator maybe? + RtlZeroMemory(&packetEntry->Samples[0], sizeof(packetEntry->Samples)); + + ExInterlockedInsertTailList(&m_PacketFifoHead, packetListEntry, &m_PacketFifoSpinLock); + + packetsToQueue -= 1; + } + } + + KeReleaseSpinLock(&m_BufferingStateSpinLock, irql); +} + +#pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetFifoStart(_Out_ ULONG *PacketNumber, _Out_ ULONGLONG *PerformanceCount) +{ + NTSTATUS status = STATUS_DEVICE_NOT_READY; + KIRQL irql = PASSIVE_LEVEL; + + // acquire the fifo spin lock in order to safely inspect the head of the fifo + KeAcquireSpinLock(&m_PacketFifoSpinLock, &irql); + + // peek at the first entry in the list, and retrieve the required packet number and qpc for it + if (!IsListEmpty(m_PacketFifoHead.Flink)) + { + PACKET_ENTRY *packetEntry; + + packetEntry = CONTAINING_RECORD(m_PacketFifoHead.Flink, PACKET_ENTRY, ListEntry); + + status = RtlLongLongToULong(packetEntry->PacketNumber, PacketNumber); + if (NT_SUCCESS(status)) + { + *PerformanceCount = packetEntry->QpcWhenSampled; + status = STATUS_SUCCESS; + } + } + + KeReleaseSpinLock(&m_PacketFifoSpinLock, irql); + + return status; +} + +#pragma code_seg() +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS CKeywordDetector::GetReadPacket +( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _In_reads_(PacketSize) PVOID *Packets, + _Out_ ULONG *PacketNumber, + _Out_ ULONG64 *PerformanceCounterValue, + _Out_ BOOLEAN *MoreData, + _Out_ ULONG *NextPacketNumber, + _Out_ ULONGLONG *NextPerformanceCount +) +{ + NTSTATUS status = STATUS_DEVICE_NOT_READY; + LIST_ENTRY *packetListEntry = NULL; + + // This call is synchronized with the dpc routine through the packet list + // spin locks, as a producer consumer relationship. + // buffering state variables are not available, and taking the buffering state + // lock here would introduce lock contention between the producer and the consumer. + *PacketNumber = 0; + *PerformanceCounterValue = 0; + *MoreData = FALSE; + *NextPacketNumber = 0; + *NextPerformanceCount = 0; + + packetListEntry = ExInterlockedRemoveHeadList(&m_PacketFifoHead, &m_PacketFifoSpinLock); + if (packetListEntry != NULL) + { + BYTE *packetData; + PACKET_ENTRY *packetEntry; + + packetEntry = CONTAINING_RECORD(packetListEntry, PACKET_ENTRY, ListEntry); + + status = RtlLongLongToULong(packetEntry->PacketNumber, PacketNumber); + if (NT_SUCCESS(status)) + { + packetData = (PBYTE) Packets[(*PacketNumber) % PacketCount]; + + *PerformanceCounterValue = packetEntry->QpcWhenSampled; + + if (NT_SUCCESS(GetFifoStart(NextPacketNumber, NextPerformanceCount))) + { + *MoreData = TRUE; + } + + // TODO: the packet size here needs to line up to the packet size allocated. + // Also, handle the first packet offset + RtlCopyMemory(packetData, packetEntry->Samples, min(sizeof(packetEntry->Samples), PacketSize)); + } + + ExInterlockedInsertTailList(&m_PacketPoolHead, packetListEntry, &m_PacketPoolSpinLock); + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::SendPropertyTo +( + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information +) +{ + PAGED_CODE(); + + ACXPIN pin; + pin = AcxCircuitGetPinById(m_Circuit, DspCapturePinTypeBridge); + RETURN_NTSTATUS_IF_TRUE(pin == NULL, STATUS_INVALID_PARAMETER); + + DSP_PIN_CONTEXT* pinCtx = GetDspPinContext(pin); + RETURN_NTSTATUS_IF_TRUE(pinCtx == NULL, STATUS_INVALID_PARAMETER); + + RETURN_NTSTATUS_IF_TRUE(pinCtx->TargetCircuit == NULL, STATUS_INVALID_DEVICE_STATE); + + ACX_REQUEST_PARAMETERS requestParams; + ACX_REQUEST_PARAMETERS_INIT_PROPERTY( + &requestParams, + PropertySet, + PropertyId, + Verb, + AcxItemTypeCircuit, + 0, + Control, ControlCb, + Value, ValueCb + ); + + WDFREQUEST request; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = m_Device; + RETURN_NTSTATUS_IF_FAILED(WdfRequestCreate(&attributes, AcxTargetCircuitGetWdfIoTarget(pinCtx->TargetCircuit), &request)); + + auto request_free = scope_exit([&request]() { + WdfObjectDelete(request); + }); + + RETURN_NTSTATUS_IF_FAILED(AcxTargetCircuitFormatRequestForProperty(pinCtx->TargetCircuit, request, &requestParams)); + + WDF_REQUEST_SEND_OPTIONS sendOptions; + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(5)); + + RETURN_NTSTATUS_IF_TRUE(!WdfRequestSend(request, AcxTargetCircuitGetWdfIoTarget(pinCtx->TargetCircuit), &sendOptions), STATUS_INVALID_DEVICE_REQUEST); + + NTSTATUS status = (WdfRequestGetStatus(request)); + + if (Information) + { + *Information = WdfRequestGetInformation(request); + } + if (status == STATUS_BUFFER_OVERFLOW && ValueCb == 0) + { + // Don't trace this error, it's normal + return status; + } + + RETURN_NTSTATUS_IF_FAILED(status); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::GetDeviceFunctionInformation +( + _Out_ PSDCA_FUNCTION_INFORMATION_LIST *FunctionInfo +) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR requiredBufferSize = 0; + + RETURN_NTSTATUS_IF_TRUE(nullptr == FunctionInfo, STATUS_INVALID_PARAMETER); + + status = SendPropertyTo(KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_FUNCTION_INFORMATION, + AcxPropertyVerbGet, + nullptr, 0, + nullptr, 0, + &requiredBufferSize); + + if (status == STATUS_BUFFER_OVERFLOW) + { + // expect a buffer overflow error, confirm size is valid + if (requiredBufferSize >= sizeof(SDCA_FUNCTION_INFORMATION_LIST)) + { + // size is valid, allocate and retrieve + *FunctionInfo = (PSDCA_FUNCTION_INFORMATION_LIST) ExAllocatePool2(POOL_FLAG_NON_PAGED, requiredBufferSize, DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(nullptr == *FunctionInfo, STATUS_INSUFFICIENT_RESOURCES); + status = SendPropertyTo(KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_FUNCTION_INFORMATION, + AcxPropertyVerbGet, + nullptr, 0, + *FunctionInfo, sizeof(SDCA_FUNCTION_INFORMATION_LIST), + nullptr); + } + else + { + // correct buffer overflow error, but size is wrong + RETURN_NTSTATUS_IF_FAILED(STATUS_UNSUCCESSFUL); + } + } + else if (NT_SUCCESS(status)) + { + // call should not succeeded with a null buffer pointer + RETURN_NTSTATUS_IF_FAILED(STATUS_INVALID_DEVICE_REQUEST); + } + + RETURN_NTSTATUS_IF_FAILED(status); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::GetDeviceKwsCapabilityDescriptor +( + _Out_ PDEVICE_KWS_CAPABILITY_DESCRIPTOR Descriptor +) +{ + PAGED_CODE(); + + memset(Descriptor, 0, sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR)); + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_DEVICE_CAPABILITY, + AcxPropertyVerbGet, + nullptr, 0, + Descriptor, sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR), + nullptr)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::GetVadDescriptor( + _Out_ PVAD_DESCRIPTOR_FORMAT Descriptor + ) +{ + PAGED_CODE(); + + // For simplicity, this sample code uses a static-sized VAD_DESCRIPTOR + // with room for 11 total formats. This still has the potential to + // fail if the target device supports more than that many formats for VAD + memset(Descriptor, 0, sizeof(VAD_DESCRIPTOR_FORMAT)); + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_VAD_CAPABILITY, + AcxPropertyVerbGet, + nullptr, 0, + Descriptor, sizeof(VAD_DESCRIPTOR_FORMAT), + nullptr)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::GetVadEntities( + _Out_ PVAD_ENTITIES_EXTRA Entities + ) +{ + PAGED_CODE(); + + // For simplicity, this sample code uses a static-sized VAD_ENTITIES + // with room for 25 total elements. This still has the potential to + // fail if the target device has more than 25 elements. + memset(Entities, 0, sizeof(VAD_ENTITIES_EXTRA)); + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_VAD_ENTITIES, + AcxPropertyVerbGet, + nullptr, 0, + Entities, sizeof(VAD_ENTITIES_EXTRA), + nullptr)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +CKeywordDetector::SetSuspendAccessEvent +( + _In_ PSDCA_KWS_NOTIFICATIONS Events +) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_ACCESS_EVENTS, + AcxPropertyVerbSet, + nullptr, 0, + Events, sizeof(SDCA_KWS_NOTIFICATIONS), + nullptr)); + + return STATUS_SUCCESS; +} + +// There are three states. Disarmed, Armed and Suspended, +// and Armed and Prepared. + +// If we're Disarmed, we need to clean up the vad stream, suspend/resume +// state doesn't matter. + +// if we're Armed and Suspended, we should be detecting but are experiencing +// a period of deafness due to the codec driver needing to access the hardware. +// So, we need to clean up the vad stream and wait for the resume notification +// to recreate the vad stream + +// if we're Armed and Prepared, then we're actively detecting, so we +// need the stream prepared. +PAGED_CODE_SEG +_Requires_lock_held_(m_csLock) +NTSTATUS +CKeywordDetector::UpdateVadStreamState() +{ + PAGED_CODE(); + + if (m_SoundDetectorArmed1 || m_SoundDetectorArmed2) + { + // if we're armed, not prepared, and not suspended, then + // we need to move to the armed and prepared state. + if (!m_Prepared && !m_Suspended) + { + // To move into the Armed and Prepared state + // we need to prepare the vad stream + RETURN_NTSTATUS_IF_FAILED(ConfigureVadPort(&m_PrepareParams)); + } + // if we are armed, prepared, and suspended, then + // we need to move to the armed and suspended state + else if (m_Prepared && m_Suspended) + { + // To move into the Armed and Suspended state + // we need to cleanup the VAD stream + RETURN_NTSTATUS_IF_FAILED(CleanupVadPort()); + } + // else + // if we are armed, prepared, and not suspended, then we are in + // the armed and prepared state, nothing else to do. + + // Or, if we are armed, not prepared, and suspended, then we are in + // the armed and suspended state, nothing else to do. + } + else + { + if (m_Prepared) + { + // moving into the disarmed state + RETURN_NTSTATUS_IF_FAILED(CleanupVadPort()); + } + } + + return STATUS_SUCCESS; +} + + +PAGED_CODE_SEG +_Requires_lock_held_(m_csLock) +NTSTATUS +CKeywordDetector::ConfigureVadPort +( + _In_ PSDCA_KWS_PREPARE_PARAMS PrepareParams +) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_CONFIGURE_VAD_PORT, + AcxPropertyVerbSet, + nullptr, 0, + PrepareParams, sizeof(SDCA_KWS_PREPARE_PARAMS), + nullptr)); + + m_Prepared = TRUE; + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_Requires_lock_held_(m_csLock) +NTSTATUS +CKeywordDetector::CleanupVadPort( ) +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(SendPropertyTo(KSPROPERTYSETID_SdcaKws, + KSPROPERTY_SDCAKWS_CLEANUP_VAD_PORT, + AcxPropertyVerbSet, + nullptr, 0, + NULL, 0, + nullptr)); + + m_Prepared = FALSE; + + return STATUS_SUCCESS; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.h new file mode 100644 index 00000000..9ebc3a5e --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/KeywordDetector.h @@ -0,0 +1,237 @@ +/*++ + +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: + + KeywordDetector.h + +Abstract: + + Sample Keyword Detector. + + +--*/ + +#pragma once + +#include <wil\resource.h> +#include "ContosoEventDetector.h" +#include "soundwirecontroller.h" +#include "sdcastreaming.h" + +#define KEYWORDDETECTOR_POOLTAG 'KWS0' + +typedef struct +{ + VAD_DESCRIPTOR Descriptor; + WAVEFORMATEXTENSIBLE ExtraFormats[10]; +} VAD_DESCRIPTOR_FORMAT, * PVAD_DESCRIPTOR_FORMAT; + +typedef struct +{ + ULONG EntitiesCount; + ENTITY_INFO ExtraEntities[25]; +} VAD_ENTITIES_EXTRA, * PVAD_ENTITIES_EXTRA; + +class CKeywordDetector +{ +public: + CKeywordDetector(_In_ WDFDEVICE Device, _In_ ACXCIRCUIT Circuit, _In_ PWAVEFORMATEXTENSIBLE Format); + + ~CKeywordDetector(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS Initialize(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS ResetDetector(_In_ GUID eventId); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS DownloadDetectorData(_In_ GUID eventId, _In_ LONGLONG Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetDetectorData(_In_ GUID eventId, _Out_ LONGLONG *Data); + + _IRQL_requires_max_(PASSIVE_LEVEL) + ULONGLONG GetStartTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + ULONGLONG GetStopTimestamp(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS SetArmed(_In_ GUID eventId, _In_ BOOLEAN Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + VOID NotifyDetection(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetArmed(_In_ GUID eventId, _Out_ BOOLEAN *Arm); + + _IRQL_requires_max_(PASSIVE_LEVEL) + VOID Run(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + VOID Stop(); + + _IRQL_requires_min_(DISPATCH_LEVEL) + VOID DpcRoutine(_In_ LONGLONG PerformanceCounter, _In_ LONGLONG PerformanceFrequency, _Out_ BOOLEAN *isRealtime, _Out_ LONGLONG *NewPacketNumber, _Out_ ULONGLONG *NewPerformanceCount); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetReadPacket(_In_ ULONG PacketCount, _In_ ULONG PacketSize, _In_reads_(PacketSize) PVOID *Packets, _Out_ ULONG *PacketNumber, + _Out_ ULONGLONG *PerformanceCount, _Out_ BOOLEAN *MoreData, _Out_ ULONG *NextPacketNumber, _Out_ ULONGLONG *NextPerformanceCount); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS GetFifoStart(_Out_ ULONG *PacketNumber, _Out_ ULONGLONG *PerformanceCount); + +private: + + _IRQL_requires_max_(PASSIVE_LEVEL) + VOID UpdateBufferingState(); + + _IRQL_requires_max_(PASSIVE_LEVEL) + NTSTATUS ReadKeywordTimestampRegistry(); + + PAGED_CODE_SEG + NTSTATUS + SendPropertyTo + ( + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information + ); + + + PAGED_CODE_SEG + NTSTATUS + GetDeviceFunctionInformation( + _Out_ PSDCA_FUNCTION_INFORMATION_LIST *FunctionInfo + ); + + PAGED_CODE_SEG + NTSTATUS + GetDeviceKwsCapabilityDescriptor( + _Out_ PDEVICE_KWS_CAPABILITY_DESCRIPTOR Descriptor + ); + + PAGED_CODE_SEG + NTSTATUS + GetVadDescriptor( + _Out_ PVAD_DESCRIPTOR_FORMAT Descriptor + ); + + PAGED_CODE_SEG + NTSTATUS + GetVadEntities ( + _Out_ PVAD_ENTITIES_EXTRA Entities + ); + + PAGED_CODE_SEG + NTSTATUS + SetSuspendAccessEvent( + _In_ PSDCA_KWS_NOTIFICATIONS Events + ); + + PAGED_CODE_SEG + _Requires_lock_held_(m_csLock) + NTSTATUS + UpdateVadStreamState(); + + PAGED_CODE_SEG + _Requires_lock_held_(m_csLock) + NTSTATUS + ConfigureVadPort( + _In_ PSDCA_KWS_PREPARE_PARAMS PrepareParams + ); + + PAGED_CODE_SEG + _Requires_lock_held_(m_csLock) + NTSTATUS + CleanupVadPort( + ); + + static KSTART_ROUTINE s_HandleNotifications; + + PAGED_CODE_SEG + void + HandleNotifications(); + + // The Contoso keyword detector processes 10ms packets of 16KHz 16-bit PCM + // audio samples + static const int SamplesPerSecond = 16000; + static const int SamplesPerPacket = (10 * SamplesPerSecond / 1000); + + typedef struct + { + LIST_ENTRY ListEntry; + LONGLONG PacketNumber; + LONGLONG QpcWhenSampled; + UINT16 Samples[SamplesPerPacket]; + } PACKET_ENTRY; + + // set at initialization, safe to use in all threads + WDFDEVICE m_Device; + ACXCIRCUIT m_Circuit; + LONGLONG m_qpcFrequency; + BOOLEAN m_Initialized; + SDCA_KWS_PREPARE_PARAMS m_PrepareParams; + PSDCA_FUNCTION_INFORMATION_LIST m_FunctionInformation; + DEVICE_KWS_CAPABILITY_DESCRIPTOR m_CapabilityDescriptor; + VAD_DESCRIPTOR_FORMAT m_VadDescriptor; + SDCA_KWS_NOTIFICATIONS m_Events; + PACKET_ENTRY m_PacketPool[1 * SamplesPerSecond / SamplesPerPacket]; // Enough storage for 1 second of audio data + VAD_ENTITIES_EXTRA m_VadEntities; + + // single thread access, no lock necessary + LONGLONG m_SoundDetectorData1; + LONGLONG m_SoundDetectorData2; + ULONGLONG m_ullKeywordStartTimestamp; + ULONGLONG m_ullKeywordStopTimestamp; + BOOLEAN m_streamRunning; + + // the following state variables are shared between dpc and stream state + KSPIN_LOCK m_BufferingStateSpinLock; + _Guarded_by_(m_BufferingStateSpinLock) + LONGLONG m_qpcStartCapture; + _Guarded_by_(m_BufferingStateSpinLock) + LONGLONG m_nLastQueuedPacket; + + // protected through interlocked access to the packet pool + KSPIN_LOCK m_PacketPoolSpinLock; + LIST_ENTRY m_PacketPoolHead; + + // protected through interlocked access to the packet pool + KSPIN_LOCK m_PacketFifoSpinLock; + LIST_ENTRY m_PacketFifoHead; + + + // the following variables are shared with the sdca notification event + // handler thread, and are protected by m_csLock + mutable wil::fast_mutex_with_critical_region m_csLock; + PETHREAD m_dispatchThread; + mutable wil::kernel_event_auto_reset m_threadExitEvent; + mutable wil::kernel_event_manual_reset m_threadExitedEvent{ true }; + + _Guarded_by_(m_csLock) + BOOLEAN m_Prepared; + + _Guarded_by_(m_csLock) + BOOLEAN m_Suspended; + + _Guarded_by_(m_csLock) + BOOLEAN m_SoundDetectorArmed1; + + _Guarded_by_(m_csLock) + BOOLEAN m_SoundDetectorArmed2; +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionClock.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionClock.h new file mode 100644 index 00000000..d57bb522 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionClock.h @@ -0,0 +1,38 @@ +/*++ + + 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: + + PositionClock.h + +Abstract: + + Simulated clock Interface for keeping track of stream position. + +Environment: + + Kernel mode + +--*/ +#pragma once + +class IPositionClock +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + virtual void Pause() = 0; + + __drv_maxIRQL(PASSIVE_LEVEL) + virtual void Run() = 0; + + __drv_maxIRQL(PASSIVE_LEVEL) + virtual void Stop() = 0; + + __drv_maxIRQL(PASSIVE_LEVEL) + virtual ULONGLONG GetElapsedTime(_Out_ PULONGLONG pQpcTimeStamp) = 0; +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.cpp new file mode 100644 index 00000000..db0f2aee --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.cpp @@ -0,0 +1,140 @@ +/*++ + + 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: + + PositionSimClock.cpp + +Abstract: + + Simulated clock for keeping track of stream position. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "PositionSimClock.h" + +#ifndef __INTELLISENSE__ +#include "positionsimclock.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CPositionSimClock::CPositionSimClock() +{ + PAGED_CODE(); + + m_State = SIM_CLOCK_STATE_STOP; + m_ElapsedTimeWhenPaused = 0; + m_StartTime = 0; + m_QpcTimeStamp = 0; + + KeInitializeSpinLock(&m_Lock); +} + +#pragma code_seg() +_Use_decl_annotations_ +CPositionSimClock::~CPositionSimClock() +{ +} + +#pragma code_seg() +_Use_decl_annotations_ +void CPositionSimClock::Run() +{ + KIRQL irql = PASSIVE_LEVEL; + KeAcquireSpinLock(&m_Lock, &irql); + + if (m_State == SIM_CLOCK_STATE_STOP || + m_State == SIM_CLOCK_STATE_PAUSE) + { + m_StartTime = KeQueryInterruptTimePrecise(&m_QpcTimeStamp); + } + + m_State = SIM_CLOCK_STATE_RUN; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"CPositionSimClock::Run SIM_CLOCK_STATE_RUN : %lld", m_StartTime); + + KeReleaseSpinLock(&m_Lock, irql); +} + +#pragma code_seg() +_Use_decl_annotations_ +void CPositionSimClock::Pause() +{ + KIRQL irql = PASSIVE_LEVEL; + KeAcquireSpinLock(&m_Lock, &irql); + + if (m_State == SIM_CLOCK_STATE_RUN) + { + m_ElapsedTimeWhenPaused = GetElapsedTimeUnlocked(); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"CPositionSimClock::Pause ElapsedTimeWhenPaused : %lld", m_ElapsedTimeWhenPaused); + } + + m_State = SIM_CLOCK_STATE_PAUSE; + + KeReleaseSpinLock(&m_Lock, irql); +} + +#pragma code_seg() +_Use_decl_annotations_ +void CPositionSimClock::Stop() +{ + KIRQL irql = PASSIVE_LEVEL; + KeAcquireSpinLock(&m_Lock, &irql); + + m_State = SIM_CLOCK_STATE_STOP; + m_StartTime = 0; + m_ElapsedTimeWhenPaused = 0; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"CPositionSimClock::Stop"); + + KeReleaseSpinLock(&m_Lock, irql); +} + +#pragma code_seg() +_Use_decl_annotations_ +ULONGLONG CPositionSimClock::GetElapsedTimeUnlocked() +{ + ULONGLONG current_time = KeQueryInterruptTimePrecise(&m_QpcTimeStamp); + + ULONGLONG elapsedTime = (current_time - m_StartTime) + m_ElapsedTimeWhenPaused; + + return elapsedTime; +} + +#pragma code_seg() +_Use_decl_annotations_ +ULONGLONG CPositionSimClock::GetElapsedTime(PULONGLONG pQpcTimeStamp) +{ + KIRQL irql = PASSIVE_LEVEL; + KeAcquireSpinLock(&m_Lock, &irql); + + ULONGLONG elapsedTime = 0; + if (m_State == SIM_CLOCK_STATE_RUN) + { + elapsedTime = GetElapsedTimeUnlocked(); + } + else + { + elapsedTime = m_ElapsedTimeWhenPaused; + } + + if (pQpcTimeStamp) + { + *pQpcTimeStamp = m_QpcTimeStamp; + } + + KeReleaseSpinLock(&m_Lock, irql); + + return elapsedTime; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.h new file mode 100644 index 00000000..2d1844fa --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/PositionSimClock.h @@ -0,0 +1,76 @@ +/*++ + + 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: + + PositionSimClock.h + +Abstract: + + Simulated clock for keeping track of stream position. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +#include "PositionClock.h" + +#define HNSTIME_PER_MILLISECOND 10000 + +class CPositionSimClock : public IPositionClock +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CPositionSimClock(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + ~CPositionSimClock(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + void Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + void Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + void Stop(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + ULONGLONG GetElapsedTime(_Out_ PULONGLONG pQpcTimeStamp); + +protected: + ULONGLONG m_StartTime; + ULONGLONG m_ElapsedTimeWhenPaused; + ULONGLONG m_QpcTimeStamp; + + KSPIN_LOCK m_Lock; + + typedef enum _SimClockState_t + { + SIM_CLOCK_STATE_STOP, + SIM_CLOCK_STATE_PAUSE, + SIM_CLOCK_STATE_RUN, + + SIM_CLOCK_STATE_Count + }SimClockState; + + SimClockState m_State; + + __drv_maxIRQL(DISPATCH_LEVEL) + ULONGLONG GetElapsedTimeUnlocked(); +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.vcxproj b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.vcxproj new file mode 100644 index 00000000..5661777a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.vcxproj @@ -0,0 +1,373 @@ +<?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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{5FDD3888-48B5-496C-83B0-E107CFFF46BC}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + <ACX_VERSION_MAJOR>1</ACX_VERSION_MAJOR> + <ACX_VERSION_MINOR>0</ACX_VERSION_MINOR> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.;..\..\..\..\..\wil\include</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_WORKAROUND_ACXFACTORYCIRCUIT_01;ACX_WORKAROUND_ACXPIN_01;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inx)" Include="*.inx" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="AcpiReader.h" /> + <ClInclude Include="CircuitHelper.h" /> + <ClInclude Include="KeywordDetector.h" /> + <ClInclude Include="..\inc\NewDelete.h" /> + <ClInclude Include="offloadStreamEngine.h" /> + <ClInclude Include="PositionClock.h" /> + <ClInclude Include="PositionSimClock.h" /> + <ClInclude Include="private.h" /> + <ClInclude Include="savedata.h" /> + <ClInclude Include="SimPeakMeter.h" /> + <ClInclude Include="streamengine.h" /> + <ClInclude Include="ToneGenerator.h" /> + <ClInclude Include="Trace.h" /> + <ClInclude Include="WaveReader.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AcpiReader.cpp" /> + <ClCompile Include="AudioModule.cpp" /> + <ClCompile Include="capture.cpp" /> + <ClCompile Include="CircuitHelper.cpp" /> + <ClCompile Include="circuitstream.cpp" /> + <ClCompile Include="device.cpp" /> + <ClCompile Include="driver.cpp" /> + <ClCompile Include="KeywordDetector.cpp" /> + <ClCompile Include="..\common\NewDelete.cpp" /> + <ClCompile Include="offloadStreamEngine.cpp" /> + <ClCompile Include="PositionSimClock.cpp" /> + <ClCompile Include="render.cpp" /> + <ClCompile Include="renderAudioEngine.cpp" /> + <ClCompile Include="savedata.cpp" /> + <ClCompile Include="SimPeakMeter.cpp" /> + <ClCompile Include="streamengine.cpp" /> + <ClCompile Include="ToneGenerator.cpp" /> + <ClCompile Include="WaveReader.cpp" /> + <ResourceCompile Include="resources.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.vcxproj.Filters new file mode 100644 index 00000000..44bc3f92 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SDCAVDsp.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"> + <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> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVApo.inx b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVApo.inx new file mode 100644 index 00000000..5b1b39d5 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVApo.inx @@ -0,0 +1,79 @@ +[Version] +Signature = "$WINDOWS NT$" +Class = AudioProcessingObject +ClassGuid = {5989fce8-9cd0-467d-8a6a-5419e31529d4} +Provider = %ProviderName% +DriverVer = 02/22/2016,1.0.0.1 +CatalogFile = sdcavad.cat +PnpLockDown = 1 + +[Manufacturer] +%MfgName% = ApoComponents,NT$ARCH$.10.0...19041 + +[ApoComponents.NT$ARCH$.10.0...19041] +%Apo.ComponentDesc% = ApoComponent_Install,SWC\VEN_SDCAV_SMPL&CID_APO + +[ApoComponent_Install] +CopyFiles = Apo_CopyFiles +AddReg = Apo_AddReg + +[Apo_CopyFiles] +sdcavkwsapo.dll + +[Apo_AddReg] +; Keyword Spotter Endpoint effect APO COM registration +HKR,Classes\CLSID\%KWS_FX_ENDPOINT_CLSID%,,,%KWS_FriendlyName% +HKR,Classes\CLSID\%KWS_FX_ENDPOINT_CLSID%\InProcServer32,,0x00020000,%13%\sdcavKWSApo.dll +HKR,Classes\CLSID\%KWS_FX_ENDPOINT_CLSID%\InProcServer32,ThreadingModel,,"Both" + +; Keyword Spotter APO registration +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"FriendlyName", ,%KWS_FriendlyName% +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"Copyright", ,%Copyright% +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MajorVersion", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MinorVersion", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"Flags", 0x00010001, 0xC +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MinInputConnections", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MaxInputConnections", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MinOutputConnections", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MaxOutputConnections", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"MaxInstances", 0x00010001, 0xffffffff +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"NumAPOInterfaces", 0x00010001, 1 +HKR,AudioEngine\AudioProcessingObjects\%KWS_FX_ENDPOINT_CLSID%,"APOInterface0", ,"{FD7F2B29-24D0-4B5C-B177-592C39F9CA10}" + +[ApoComponent_Install.HW] +AddReg = FriendlyName_AddReg + +[FriendlyName_AddReg] +HKR,,FriendlyName,,%Apo.ComponentDesc% + +[ApoComponent_Install.Services] +AddService=,2 ; no function driver, install a null driver. + +[SourceDisksNames] +1 = Disk + +[SourceDisksFiles] +sdcavkwsapo.dll = 1 + +[DestinationDirs] +Apo_CopyFiles = 13 ; 13=Package's DriverStore directory + +[SignatureAttributes] +sdcavkwsapo.dll = SignatureAttributes.PETrust + +[SignatureAttributes.PETrust] +PETrust = true + +[Strings] +MfgName = "TODO-Set-Manufacturer" +ProviderName = "TODO-Set-Provider" +Apo.ComponentDesc = "Audio SDCAV APO Sample" + +; Driver developers would replace these CLSIDs with those of their own APOs +KWS_FX_ENDPOINT_CLSID = "{9D89F614-F9D6-40DD-9F21-5E69FA3981ED}" + +; see audioenginebaseapo.idl for APO_FLAG enum values +APO_FLAG_DEFAULT = 0x0000000e + +KWS_FriendlyName = "Keyword Spotter APO Sample (endpoint effect)" +Copyright = "Sample" diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVDsp.inx b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVDsp.inx new file mode 100644 index 00000000..a0e0a654 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SdcaVDsp.inx @@ -0,0 +1,159 @@ +;/*++ +; +;Copyright (c) Microsoft Corporation. All rights reserved. +; +;Module Name: +; +; SDCAVDsp.INF +; +;--*/ + +[Version] +Signature="$WINDOWS NT$" +Class=MEDIA +ClassGuid={4d36e96c-e325-11ce-bfc1-08002be10318} +Provider=%ProviderName% +DriverVer=06/13/2016, 1.0.0.1 +CatalogFile=SDCAVad.cat +PnpLockdown=1 + +[DestinationDirs] +DefaultDestDir = 13 + +;***************************************** +; Audio Device Install Section +;***************************************** +[ControlFlags] +ExcludeFromSelect = {4DCB0606-6415-4A36-BDC5-9B1792117DC9}\Render +ExcludeFromSelect = {4DCB0606-6415-4A36-BDC5-9B1792117DC9}\Capture + +[Manufacturer] +%StdMfg%=Standard,NT$ARCH$.10.0...19041 + +[Standard.NT$ARCH$.10.0...19041] +%WdfDspDevice.DeviceDesc%=Audio_Device, SOUNDWIRETEST\DSP +%WdfDspDevice.DeviceDesc%=Audio_Child_Device, {4DCB0606-6415-4A36-BDC5-9B1792117DC9}\Render +%WdfDspDevice.DeviceDesc%=Audio_Child_Device, {4DCB0606-6415-4A36-BDC5-9B1792117DC9}\Capture + +[Audio_Device.NT] +CopyFiles=Audio_Device.NT.Copy +AddReg=EVENTDETECTORCONTOSOADAPTER.AddReg + +[Audio_Child_Device.NT] +CopyFiles=Audio_Device.NT.Copy + +[Audio_Device.NT.Copy] +SDCAVDsp.sys +EventDetectorContosoAdapter.dll + +;-------------- Service installation + +[Audio_Device.NT.Services] +AddService = SDCAVDsp, %SPSVCINST_ASSOCSERVICE%, Audio_Service_Inst + +[Audio_Child_Device.NT.Services] +;NULL Driver +AddService = , %SPSVCINST_ASSOCSERVICE% + +[Audio_Service_Inst] +DisplayName = %WdfDspDevice.DeviceDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %13%\SDCAVDsp.sys + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +SDCAVDsp.sys = 1,, +EventDetectorContosoAdapter.dll = 1,, + +[Audio_Device.NT.Wdf] +KmdfService = SDCAVDsp, Audio_wdfsect +[Audio_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + +[EVENTDETECTORCONTOSOADAPTER.AddReg] +HKCR,CLSID\%EVENTDETECTORCONTOSOADAPTER_CLSID2%,,,"EventDetectorContosoAdapter2 Class" +HKCR,CLSID\%EVENTDETECTORCONTOSOADAPTER_CLSID2%\InProcServer32,,0x00020000,%13%\eventdetectorcontosoadapter.dll +HKCR,CLSID\%EVENTDETECTORCONTOSOADAPTER_CLSID2%\InProcServer32,ThreadingModel,,"Apartment" +HKCR,CLSID\%EVENTDETECTORCONTOSOADAPTER_CLSID2%\Version,,,"1.0" + +; +; render interfaces: speaker +; +[Audio_Device.I.Speaker] +AddReg=Audio_Device.I.Speaker.AddReg +[Audio_Device.I.Speaker.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%Audio_Device.Speaker.szPname% +; The following lines opt-in to pull mode. +HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY% +HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1 + +; +; capture interfaces: microphone +; +[Audio_Device.I.Microphone] +AddReg=Audio_Device.I.Microphone.AddReg +[Audio_Device.I.Microphone.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%Audio_Device.Microphone.szPname% +; The following lines opt-in to pull mode. +HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY% +HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1 + +; +; PnP add interface directives for dynamic enumerated audio endpoints. +; +[Audio_Child_Device.NT.Interfaces] +; Interfaces for render endpoint. capture is used for loopback. +AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Speaker%, Audio_Device.I.Speaker +AddInterface=%KSCATEGORY_RENDER%, %KSNAME_Speaker%, Audio_Device.I.Speaker +AddInterface=%KSCATEGORY_REALTIME%, %KSNAME_Speaker%, Audio_Device.I.Speaker +;AddInterface=%KSCATEGORY_CAPTURE%, %KSNAME_Speaker%, Audio_Device.I.Speaker + +; Interfaces for mic capture endpoint +AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Microphone%, Audio_Device.I.Microphone +AddInterface=%KSCATEGORY_CAPTURE%, %KSNAME_Microphone%, Audio_Device.I.Microphone +AddInterface=%KSCATEGORY_REALTIME%, %KSNAME_Microphone%, Audio_Device.I.Microphone + +[Strings] +; +;Non-localizable +; +KSNAME_Speaker="Speaker0" +KSNAME_Microphone="Microphone0" + +SPSVCINST_ASSOCSERVICE = 0x00000002 +ProviderName = "VS_Microsoft" + +Proxy.CLSID = "{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO = "{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER = "{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_REALTIME = "{EB115FFC-10C8-4964-831D-6DCB02E6F23F}" + +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +KSNODETYPE_ANY = "{00000000-0000-0000-0000-000000000000}" + +PKEY_AudioEndpoint_ControlPanelPageProvider = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},1" +PKEY_AudioEndpoint_Association = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},2" +PKEY_AudioEndpoint_Supports_EventDriven_Mode = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},7" +PKEY_AudioEndpoint_Default_VolumeInDb = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},9" + +; Driver developers would replace this CLSID with their own keyword detector OEM adapter +EVENTDETECTORCONTOSOADAPTER_CLSID2 = {207F3D0C-5C79-496F-A94C-D3D2934DBFA9} + +; +;Localizable +; +StdMfg = "SDCA Virtual Dsp Audio Device" +DiskId1 = "SDCA Virtual Dsp Audio Driver Installation Disk" +WdfDspDevice.DeviceDesc = "SDCA Virtual Dsp Audio Driver" + +;; friendly names +Audio_Device.Speaker.szPname="SDCA Virtual DSP Speaker" +Audio_Device.Microphone.szPname="SDCA Virtual DSP Microphone" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.cpp new file mode 100644 index 00000000..0dfbd4e5 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.cpp @@ -0,0 +1,106 @@ +/*++ + + 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: + + SimPeakMeter.cpp + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "SimPeakMeter.h" + +#ifndef __INTELLISENSE__ +#include "SimPeakMeter.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::CSimPeakMeter() +{ + PAGED_CODE(); + m_NumStreams = 0; + m_PeakMeterIndex = 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter::~CSimPeakMeter() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +LONG CSimPeakMeter::GetValue(ULONG Channel) +{ + PAGED_CODE(); + + // Ignore channel + UNREFERENCED_PARAMETER(Channel); + +#define PEAKMETER_VALUE_FULL (PEAKMETER_MAXIMUM / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_HALF (PEAKMETER_MAXIMUM / 2 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_QUARTER (PEAKMETER_MAXIMUM / 4 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) +#define PEAKMETER_VALUE_ONE_EIGTH (PEAKMETER_MAXIMUM / 8 / PEAKMETER_STEPPING_DELTA * PEAKMETER_STEPPING_DELTA) + + LONG PeakMeterValues[] = { + PEAKMETER_VALUE_ONE_EIGTH, + PEAKMETER_VALUE_QUARTER, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_FULL, + PEAKMETER_VALUE_HALF, + PEAKMETER_VALUE_QUARTER + }; + + if (m_NumStreams) + { + LONG pmi = InterlockedIncrement(&m_PeakMeterIndex); + if (pmi == ARRAYSIZE(PeakMeterValues)) + { + pmi = 0; + InterlockedExchange(&m_PeakMeterIndex, 0); + } + + return PeakMeterValues[pmi]; + } + + // + // No active streams. Peak meter = 0 + // + return 0; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StartStream() +{ + PAGED_CODE(); + InterlockedIncrement(&m_NumStreams); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CSimPeakMeter::StopStream() +{ + PAGED_CODE(); + + ASSERT(m_NumStreams); + InterlockedDecrement(&m_NumStreams); + + return STATUS_SUCCESS; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.h new file mode 100644 index 00000000..7203f299 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/SimPeakMeter.h @@ -0,0 +1,51 @@ +/*++ + + 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: + + SimPeakMeter.h + +Abstract: + + Virtual Peakmeter - aggregates all streams + +Environment: + + Kernel mode + +--*/ + +#pragma once + +class CSimPeakMeter +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSimPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + LONG GetValue(_In_ ULONG Channel); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StartStream(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS StopStream(); + +private: + LONG m_NumStreams; + LONG m_PeakMeterIndex; +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.cpp new file mode 100644 index 00000000..f98067c2 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.cpp @@ -0,0 +1,329 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + ToneGenerator + +Abstract: + + Implementation of a generic sine wave generator. + +--*/ + +#include <ntdef.h> +#include <wdm.h> +#include <minwindef.h> +#define NOBITMAP +#include <mmreg.h> +#undef NOBITMAP + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +#include <ToneGenerator.h> + +#define TONEGENERATOR_POOLTAG 'TGMP' + +const double TWO_PI = M_PI * 2; + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +// +// Double to long conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +#pragma code_seg() +long ConvertToLong(double Value) +{ + return (long)(Value * _I32_MAX); +}; + +// +// Double to short conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +#pragma code_seg() +short ConvertToShort(double Value) +{ + return (short)(Value * _I16_MAX); +}; + +// +// Double to char conversion. +// +__drv_maxIRQL(DISPATCH_LEVEL) +#pragma code_seg() +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. +// +_Use_decl_annotations_ +__declspec(code_seg("PAGE")) +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. +// +_Use_decl_annotations_ +__declspec(code_seg("PAGE")) +ToneGenerator::~ToneGenerator() +{ + if (m_PartialFrame) + { + ExFreePoolWithTag(m_PartialFrame, TONEGENERATOR_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) + +_Use_decl_annotations_ +#pragma code_seg() +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. +// +// +_Use_decl_annotations_ +#pragma code_seg() +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) + { + 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; +} + +_Use_decl_annotations_ +__declspec(code_seg("PAGE")) +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, + TONEGENERATOR_POOLTAG); + + IF_TRUE_ACTION_JUMP(m_PartialFrame == NULL, status = STATUS_INSUFFICIENT_RESOURCES, Done); + + status = STATUS_SUCCESS; + +Done: + return status; +} + +_Use_decl_annotations_ +__declspec(code_seg("PAGE")) +NTSTATUS ToneGenerator::Init +( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt +) +{ + return Init(ToneFrequency, 0.5, 0, 0, WfExt); +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.h new file mode 100644 index 00000000..c9fd08fc --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/ToneGenerator.h @@ -0,0 +1,93 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + ToneGenerator.h + +Abstract: + + Declaration of a generic sine wave generator. + +--*/ +#ifndef _SAMPLE_TONEGENERATOR_H +#define _SAMPLE_TONEGENERATOR_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: + __drv_maxIRQL(PASSIVE_LEVEL) + __declspec(code_seg("PAGE")) + ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + __declspec(code_seg("PAGE")) + ~ToneGenerator(); + + __drv_maxIRQL(PASSIVE_LEVEL) + __declspec(code_seg("PAGE")) + NTSTATUS + Init + ( + _In_ DWORD ToneFrequency, + _In_ double ToneAmplitude, + _In_ double ToneDCOffset, + _In_ double ToneInitialPhase, + _In_ PWAVEFORMATEXTENSIBLE WfExt + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + __declspec(code_seg("PAGE")) + NTSTATUS + Init + ( + _In_ DWORD ToneFrequency, + _In_ PWAVEFORMATEXTENSIBLE WfExt + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + GenerateSine + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ size_t BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + __declspec(code_seg("PAGE")) + VOID + SetMute + ( + _In_ bool Value + ) + { + m_Mute = Value; + } + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID InitNewFrame + ( + _Out_writes_bytes_(FrameSize) BYTE* Frame, + _In_ DWORD FrameSize + ); +}; + +#endif // _SAMPLE_TONEGENERATOR_H diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/Trace.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/Trace.h new file mode 100644 index 00000000..e029aad0 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/Trace.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + +Trace.h + +--*/ + +#pragma once + +#include <WppRecorder.h> +#include <evntrace.h> // For TRACE_LEVEL definitions + +#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) +#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4) + +// {CDB67DAC-8621-4E28-97A9-9C6EAFAA4A64} +#define WPP_CONTROL_GUIDS \ +WPP_DEFINE_CONTROL_GUID(DrvLogger,(cdb67dac,8621,4e28,97a9,9c6eafaa4a64), \ + WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \ + ) + +#include "trace_macros.h" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.cpp new file mode 100644 index 00000000..d7b04892 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.cpp @@ -0,0 +1,772 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + WaveReader.cpp + +Abstract: + Implementation of ACX DSP Test Driver wave file reader + + To read data from disk, this class maintains a circular data buffer. This buffer is segmented into multiple chunks of + big buffer (Though we only need two, so it is set to two now). Initially we fill first two chunks and once a chunk gets emptied + by OS, we schedule a workitem to fill the next available chunk. + + +--*/ + +#pragma warning (disable : 4127) +#pragma warning (disable : 26165) + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "WaveReader.h" + +#define FILE_NAME_BUFFER_TAG 'WRT1' +#define WAVE_DATA_BUFFER_TAG 'WRT2' +#define WORK_ITEM_BUFFER_TAG 'WRT3' + +#define MAX_READ_WORKER_ITEM_COUNT 15 + +#define IF_FAILED_JUMP(result, tag) do {if (!NT_SUCCESS(result)) {goto tag;}} while(false) +#define IF_TRUE_JUMP(result, tag) do {if (result) {goto tag;}} while(false) +#define IF_TRUE_ACTION_JUMP(result, action, tag) do {if (result) {action; goto tag;}} while(false) + +PREADWORKER_PARAM CWaveReader::m_pWorkItems = NULL; +PDEVICE_OBJECT CWaveReader::m_pDeviceObject = NULL; + + +/*++ + +Routine Description: + Ctor: basic init. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::CWaveReader() +: m_ChannelCount(0), + m_BitsPerSample(0), + m_SamplesPerSecond(0), + m_Mute(false), + m_FileHandle(NULL) +{ + PAGED_CODE(); + m_WaveDataQueue.pWavData = NULL; + KeInitializeMutex(&m_FileSync, 0); +} + +/*++ + +Routine Description: + Dtor: free resources. + +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +CWaveReader::~CWaveReader() +{ + PAGED_CODE(); + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (m_WaveDataQueue.pWavData != NULL) + { + ExFreePoolWithTag(m_WaveDataQueue.pWavData, WAVE_DATA_BUFFER_TAG); + m_WaveDataQueue.pWavData = NULL; + } + + FileClose(); + KeReleaseMutex(&m_FileSync, FALSE); + } + +} + +/*++ + +Routine Description: + - Initializing the workitems. These workitems will be scheduled asynchronously by the OS. + - When these work items will be scheduled the wave file will be read and the data + - will be put inside the big chunks. + +Arguments: + Device object + +Return Value: + NT status code. + +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::InitializeWorkItems(PDEVICE_OBJECT DeviceObject) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_pWorkItems != NULL) + { + return ntStatus; + } + + m_pWorkItems = (PREADWORKER_PARAM) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + sizeof(READWORKER_PARAM) * MAX_READ_WORKER_ITEM_COUNT, + 'RDPT' + ); + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_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; +} + +/*++ + +Routine Description: +- Wait for all the scheduled workitems to finish. + +--*/ + + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void CWaveReader::WaitAllWorkItems() +{ + PAGED_CODE(); + + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} + +/*++ + +Routine Description: + - Deallocating the workitems. + +--*/ + + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID CWaveReader::DestroyWorkItems() +{ + PAGED_CODE(); + + if (m_pWorkItems) + { + for (int i = 0; i < MAX_READ_WORKER_ITEM_COUNT; i++) + { + if (m_pWorkItems[i].WorkItem != NULL) + { + IoFreeWorkItem(m_pWorkItems[i].WorkItem); + m_pWorkItems[i].WorkItem = NULL; + } + } + ExFreePoolWithTag(m_pWorkItems, WORK_ITEM_BUFFER_TAG); + m_pWorkItems = NULL; + } +} + +/*++ + +Routine Description: + - Get a free work item to schedule a file read operation. + +--*/ +_Use_decl_annotations_ +#pragma code_seg() +PREADWORKER_PARAM CWaveReader::GetNewWorkItem() +{ + LARGE_INTEGER timeOut = { 0 }; + NTSTATUS ntStatus; + + for (int i = 0; i < MAX_READ_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; +} + +/*++ +Routine Description: +- This routine will enqueue a workitem for reading wave file and putting +- the data into the chunk buffer. + +Arguments: + Chunk descriptor for the chunk to be filled. +--*/ + +_Use_decl_annotations_ +#pragma code_seg() +VOID CWaveReader::ReadWavChunk(PCHUNKDESCRIPTOR pChunkDescriptor) +{ + PREADWORKER_PARAM pParam = NULL; + + pParam = GetNewWorkItem(); + if (pParam) + { + pParam->PtrWaveReader = this; + pParam->PtrChunkDescriptor = pChunkDescriptor; + KeResetEvent(&pParam->EventDone); + IoQueueWorkItem(pParam->WorkItem, ReadFrameWorkerCallback, + DelayedWorkQueue, (PVOID)pParam); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +/* +Routine Description: +- This routine will be called by the OS. It will fill the chunk buffer, defined by the chunk descriptor +- If end of file is reached it will mark the end of file as true. + +Arguments: + pDeviceObject - Device object + Context - pointer to reader worker params +*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID ReadFrameWorkerCallback +( + PDEVICE_OBJECT pDeviceObject, + PVOID Context +) +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(pDeviceObject); + pWaveReader pWavRd; + PREADWORKER_PARAM pParam = (PREADWORKER_PARAM)Context; + + if (NULL == pParam) + { + // This is completely unexpected, assert here. + // + ASSERT(pParam); + goto exit; + } + + pWavRd = pParam->PtrWaveReader; + + if (pWavRd == NULL) + { + goto exit; + } + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &pWavRd->m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + + NTSTATUS ntStatus = STATUS_SUCCESS; + + ASSERT(Context); + + IO_STATUS_BLOCK ioStatusBlock; + + if (pParam->WorkItem) + { + if (pWavRd->m_WaveDataQueue.bEofReached || pWavRd->m_WaveDataQueue.pWavData == NULL) + { + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + goto exit; + } + + if (pParam->PtrChunkDescriptor->pStartAddress != NULL) + { + ntStatus = ZwReadFile(pWavRd->m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + pParam->PtrChunkDescriptor->pStartAddress, + pParam->PtrChunkDescriptor->ulChunkLength, + NULL, + NULL); + + pParam->PtrChunkDescriptor->bIsChunkEmpty = false; + + if (ioStatusBlock.Information != pParam->PtrChunkDescriptor->ulChunkLength) + { + pWavRd->m_WaveDataQueue.bEofReached = true; + } + } + } + + KeReleaseMutex(&pWavRd->m_FileSync, FALSE); + } + +exit: + KeSetEvent(&pParam->EventDone, 0, FALSE); +} + +/*++ + +Routine Description: +- If all the chunks are empty this resturn true. + +--*/ + +_Use_decl_annotations_ +#pragma code_seg() +bool CWaveReader::IsAllChunkEmpty() +{ + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + if (!m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty) + { + return false; + } + } + return true; +} + +/*++ +Routine Description: + - This routine does the actual copy of data from the chunk buffer to the buffer provided by OS. + - If it empties the current chunk buffer, then it sets it state to empty and then enqueue a workitem + - to read data from the wave file and put it to the next available chunk buffer. + +Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) + +--*/ +_Use_decl_annotations_ +#pragma code_seg() +VOID CWaveReader::CopyDataFromRingBuffer +( + BYTE *Buffer, + ULONG BufferLength +) +{ + if (IsAllChunkEmpty()) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + ULONG prevChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ )/ m_WaveDataQueue.ulLength; + + ///////////////// + BYTE *currentBuf = Buffer; + ULONG length = BufferLength; + while (length > 0) + { + ULONG runWrite = min(length, m_WaveDataQueue.ulLength - m_WaveDataQueue.ulReadPtr); + + // Copy the wave buffer data to OS buffer + RtlCopyMemory(currentBuf, m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Zero out the wave buffer, so that if wave end of file is reached we should copy only zeros + RtlZeroMemory(m_WaveDataQueue.pWavData + m_WaveDataQueue.ulReadPtr, runWrite); + // Update the read pointer + m_WaveDataQueue.ulReadPtr = (m_WaveDataQueue.ulReadPtr + runWrite) % m_WaveDataQueue.ulLength; + currentBuf += runWrite; + length = length - runWrite; + } + + ULONG curChunk = (m_WaveDataQueue.ulReadPtr*NUM_OF_CHUNK_FOR_FILE_READ) / m_WaveDataQueue.ulLength; + + if (curChunk != prevChunk) + { + m_WaveDataQueue.currentExecutedChunk++; + // Schedule a workitem to read data from the wave file + ULONG chunkNo = m_WaveDataQueue.currentExecutedChunk % NUM_OF_CHUNK_FOR_FILE_READ; + m_WaveDataQueue.sChunkDescriptor[chunkNo].bIsChunkEmpty = true; + if (!m_WaveDataQueue.bEofReached) + { + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[chunkNo]); + } + } + } +} + +/*++ +Routine Description: + - Just a high level read buffer call. + + Arguments: + Buffer - Pointer to the OS buffer + BufferLength - Length of the data to be filled (in bytes) +--*/ + +_Use_decl_annotations_ +#pragma code_seg() +VOID CWaveReader::ReadWaveData +( + BYTE *Buffer, + ULONG BufferLength +) +{ + if (m_Mute) + { + RtlZeroMemory(Buffer, BufferLength); + } + else + { + CopyDataFromRingBuffer(Buffer, BufferLength); + } +} + +/*++ +Routine Description: +- initialization for the wavereader member variables, +- Allocating memory for the 1 second buffer +- Preread the one second buffer data, so that when OS comes to read the data we have it available in the memory. + +Arguments: + WfExt - Format which should be used for capture + fileNameString - name of the file to be read + +Return: + NTStatus +--*/ +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::Init +( + PWAVEFORMATEXTENSIBLE WfExt, + PUNICODE_STRING puiFileName +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + KFLOATING_SAVE saveData; + + // Save floating state (just in case). + ntStatus = KeSaveFloatingPointState(&saveData); + if (!NT_SUCCESS(ntStatus)) + { + return ntStatus; + } + + // + // This sample supports PCM 16bit formats only. + // + if ((WfExt->Format.wFormatTag != WAVE_FORMAT_PCM && + !(WfExt->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && + IsEqualGUIDAligned(WfExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))) || + (WfExt->Format.wBitsPerSample != 16 && + WfExt->Format.wBitsPerSample != 8)) + { + ntStatus = STATUS_NOT_SUPPORTED; + } + IF_FAILED_JUMP(ntStatus, Done); + + // Basic init. + 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; + + // Wave data queue initialization + m_WaveDataQueue.ulLength = WfExt->Format.nAvgBytesPerSec; + m_WaveDataQueue.bEofReached = false; + m_WaveDataQueue.ulReadPtr = 0; + + // Mark all the chunk empty + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].bIsChunkEmpty = true; + } + + ntStatus = OpenWaveFile(puiFileName); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = AllocateBigBuffer(); + IF_FAILED_JUMP(ntStatus, Done); + + ntStatus = ReadHeaderAndFillBuffer(); + +Done: + (void)KeRestoreFloatingPointState(&saveData); + return ntStatus; +} + +/*++ +Routine Description: + This function read the wave header file and compare the header info with the + stream info. Currently we are using only number of channel, sampling frequency + and bits per sample as the primary parameters for the wave file to compare against + stream params. If the params don't match we return success but streams zeros. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::ReadHeaderAndFillBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + ntStatus = FileReadHeader(); + + if(NT_SUCCESS(ntStatus)) + { + if (m_WaveHeader.numChannels != m_ChannelCount || + m_WaveHeader.bitsPerSample != m_BitsPerSample || + m_WaveHeader.sampleRate != m_SamplesPerSecond) + { + // If the wave file format don't match we wont treat this as error + // and we will stream zeros. So we return from here and will not read the + // wave file and wont fill the buffers. + return STATUS_SUCCESS; + } + } + + if (NT_SUCCESS(ntStatus)) + { + // If the wave file format is same as the stream format we will stream the data + // else we will just stream zeros. + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[0]); // Fill the first chunk + ReadWavChunk(&m_WaveDataQueue.sChunkDescriptor[1]); // Fill the second chunk + // Set the current executed chunk to 1. Once OS finishs the data for the first chunk + // use the currentExecutedChunk to find the next chunk and schedule a workitem to fill the + // data into the next chunk + m_WaveDataQueue.currentExecutedChunk = 1; + } + + return ntStatus; +} + +/*++ +Routine Description: + This function allocates 1 second buffer. + Segments the buffer into multiple (currently two) chunks. Assigns the start pointer and length + for each chunk. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::AllocateBigBuffer() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_WaveDataQueue.pWavData = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_WaveDataQueue.ulLength, + WAVE_DATA_BUFFER_TAG + ); + if (!m_WaveDataQueue.pWavData) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + // ExAllocatePool2 zeros memory. + + ULONG chunklLength = m_WaveDataQueue.ulLength / NUM_OF_CHUNK_FOR_FILE_READ; + for (int i = 0; i < NUM_OF_CHUNK_FOR_FILE_READ; i++) + { + m_WaveDataQueue.sChunkDescriptor[i].pStartAddress = m_WaveDataQueue.pWavData + chunklLength*i; + m_WaveDataQueue.sChunkDescriptor[i].ulChunkLength = chunklLength; + } + } + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Arguments: + fileNameString - Name of the wave file + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::OpenWaveFile(PUNICODE_STRING puiFileName) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (NT_SUCCESS(ntStatus) && puiFileName->Buffer != NULL) + { + // Create data file. + InitializeObjectAttributes + ( + &m_objectAttributes, + puiFileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL + ); + + // Open Wave File + ntStatus = FileOpen(); + } + + return ntStatus; +} + +/*++ +Routine Description: + This function closes wave file handle. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileClose() +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} + +/*++ +Routine Description: + Reads the wave file file header information + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileReadHeader() +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + + ntStatus = ZwReadFile(m_FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + &m_WaveHeader, + sizeof(WAVEHEADER), + NULL, + NULL); + + return ntStatus; +} + +/*++ +Routine Description: + This function opens wave file. + +Return: + NTStatus +--*/ + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS CWaveReader::FileOpen() +{ + + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + IO_STATUS_BLOCK ioStatusBlock; + + if (!m_FileHandle) + { + ntStatus = + ZwCreateFile + ( + &m_FileHandle, + GENERIC_READ, + &m_objectAttributes, + &ioStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + } + + return ntStatus; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.h new file mode 100644 index 00000000..2d5c537f --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/WaveReader.h @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + WaveReader.h + +Abstract: + + Declaration of ACX DSP Test Driver wave reader. + + +--*/ +#pragma once + +#define _USE_MATH_DEFINES +#include <math.h> +#include <limits.h> + +#define NUM_OF_CHUNK_FOR_FILE_READ 2 + +class CWaveReader; + +// Wave header structure decleration +typedef CWaveReader *pWaveReader; +typedef struct _WAVEHEADER +{ + BYTE chunkId[4]; + ULONG chunkSize; + BYTE format[4]; + BYTE subChunkId[4]; + ULONG subChunkSize; + WORD audioFormat; + WORD numChannels; + ULONG sampleRate; + ULONG bytesPerSecond; + WORD blockAlign; + WORD bitsPerSample; + BYTE dataChunkId[4]; + ULONG dataSize; +}WAVEHEADER; + +typedef struct _CHUNKDESCRIPTOR +{ + PBYTE pStartAddress; // Starting address of the chunk + ULONG ulChunkLength; // Length of the chunk + bool bIsChunkEmpty; // If the chunk is empty +}CHUNKDESCRIPTOR; +typedef CHUNKDESCRIPTOR *PCHUNKDESCRIPTOR; + +/* + The idea here is to allocate one second long worth of buffer and divide it into NUM_OF_CHUNK_FOR_FILE_READ chunks. + In one file read operation we read and fill one chunk data . The chunk will be emptied every 10 ms by OS. + Once the OS empties one chunk data we schedule a workitem to read and fill next available chunk. +*/ + +typedef struct _WAVEDATAQUEUE +{ + PBYTE pWavData; // Pointer to the temporary buffer for reading one second worth of data from wave file + ULONG ulLength; // length of pWavData in bytes + ULONG ulReadPtr; // current reading position in pWavData in bytes + bool bEofReached; // This will be set once the eof is reached. + WORD currentExecutedChunk; + CHUNKDESCRIPTOR sChunkDescriptor[NUM_OF_CHUNK_FOR_FILE_READ]; +}WAVEDATAQUEUE; +typedef WAVEDATAQUEUE *PWAVEDATAQUEUE; + +// Parameter to workitem. +#include <pshpack1.h> +typedef struct _READWORKER_PARAM { + PIO_WORKITEM WorkItem; // Pointer to the workitem + KEVENT EventDone; // Used for synchronizing a workitem for scheduling. + pWaveReader PtrWaveReader; // pointer to the wavereader class. + PCHUNKDESCRIPTOR PtrChunkDescriptor; // chunk descriptor for the chunk, which needs to be filled after file read +} READWORKER_PARAM; +typedef READWORKER_PARAM *PREADWORKER_PARAM; +#include <poppack.h> + +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; + +// Wave Reader class + +class CWaveReader +{ + +public: + HANDLE m_FileHandle; // Wave File handle. + WORD m_ChannelCount; // Number of Channels for the stream during stream init + WORD m_BitsPerSample; // Number of Bits per sample for the stream during stream init + DWORD m_SamplesPerSecond; // Number of Sample per second for the stream during stream init + bool m_Mute; // Capture Zero buffer if mute + OBJECT_ATTRIBUTES m_objectAttributes; // Used for opening file. + WAVEDATAQUEUE m_WaveDataQueue; // Big buffer data object and its current state + KMUTEX m_FileSync; // Synchronizes file access + WAVEHEADER m_WaveHeader; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CWaveReader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS Init + ( + _In_ PWAVEFORMATEXTENSIBLE WfExt, + _In_ PUNICODE_STRING puiFileName + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID ReadWaveData + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID SetMute(_In_ bool Value) + { + PAGED_CODE(); + + m_Mute = Value; + } + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void WaitAllWorkItems(); + + // Static allocation totally related to the workitems for reading data from wavefile and putting it to chunk buffer + static PDEVICE_OBJECT m_pDeviceObject; + static PREADWORKER_PARAM m_pWorkItems; + PAGED_CODE_SEG + static NTSTATUS InitializeWorkItems(_In_ PDEVICE_OBJECT DeviceObject); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + static PREADWORKER_PARAM GetNewWorkItem(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + static VOID DestroyWorkItems(); + +private: + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID ReadWavChunk(PCHUNKDESCRIPTOR PtrChunkDescriptor); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + bool IsAllChunkEmpty(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS OpenWaveFile(PUNICODE_STRING puiFileName); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileClose(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileReadHeader(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS FileOpen(); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID CopyDataFromRingBuffer + ( + _Out_writes_bytes_(BufferLength) BYTE *Buffer, + _In_ ULONG BufferLength + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS AllocateBigBuffer(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS ReadHeaderAndFillBuffer(); + + friend IO_WORKITEM_ROUTINE ReadFrameWorkerCallback; +}; + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/capture.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/capture.cpp new file mode 100644 index 00000000..eccd5738 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/capture.cpp @@ -0,0 +1,1465 @@ +/*++ + + 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: + + capture.cpp + +Abstract: + + capture factory and circuit + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "CircuitHelper.h" + +#include "TestProperties.h" +#include "KeywordDetector.h" +#include "sdcastreaming.h" + +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "capture.tmh" +#endif + +// +// max # of streams. +// +#define DSPC_MAX_OUTPUT_SYSTEM_STREAMS 1 +#define DSPC_MAX_OUTPUT_KEYWORDDETECTOR_STREAMS 1 + +// +// Factory circuit IDs. +// +#define CAPTURE_DEVICE_ID_STR L"{4DCB0606-6415-4A36-BDC5-9B1792117DC9}\\Capture&CP_%wZ" +DECLARE_CONST_UNICODE_STRING(CaptureHardwareId, L"{4DCB0606-6415-4A36-BDC5-9B1792117DC9}\\Capture"); + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxKeywordSpotterRetrieveArm( + _In_ ACXKEYWORDSPOTTER KeywordSpotter, + _In_ GUID * EventId, + _Out_ BOOLEAN * Arm +) +{ + PAGED_CODE(); + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + CKeywordDetector * keywordDetector = NULL; + + keywordSpotterCtx = GetDspKeywordSpotterContext(KeywordSpotter); + + keywordDetector = (CKeywordDetector*)keywordSpotterCtx->KeywordDetector; + + RETURN_NTSTATUS_IF_FAILED(keywordDetector->GetArmed(*EventId, Arm)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxKeywordSpotterAssignArm( + _In_ ACXKEYWORDSPOTTER KeywordSpotter, + _In_ GUID * EventId, + _In_ BOOLEAN Arm +) +{ + PAGED_CODE(); + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + CKeywordDetector * keywordDetector = NULL; + + keywordSpotterCtx = GetDspKeywordSpotterContext(KeywordSpotter); + + keywordDetector = (CKeywordDetector*)keywordSpotterCtx->KeywordDetector; + + RETURN_NTSTATUS_IF_FAILED(keywordDetector->SetArmed(*EventId, Arm)); + + // the following code is for example only, after arming the + // requested keyword we immediately trigger a detection + // so that the automated tests do not block. + if (Arm) + { + CONTOSO_KEYWORDDETECTIONRESULT detectionResult; + + // notify the keyword detector that we have a notification, to populate + // timestamp information for this detection. + keywordDetector->NotifyDetection(); + + // fill in the detection specific information + detectionResult.EventId = *EventId; + detectionResult.Header.Size = sizeof(CONTOSO_KEYWORDDETECTIONRESULT); + detectionResult.Header.PatternType = CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + detectionResult.KeywordStartTimestamp = keywordDetector->GetStartTimestamp(); + detectionResult.KeywordStopTimestamp = keywordDetector->GetStopTimestamp(); + keywordDetector->GetDetectorData(*EventId, &(detectionResult.ContosoDetectorResultData)); + + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(keywordSpotterCtx->Event, &detectionResult, sizeof(CONTOSO_KEYWORDDETECTIONRESULT))); + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxKeywordSpotterAssignPatterns( + _In_ ACXKEYWORDSPOTTER KeywordSpotter, + _In_ GUID * EventId, + _In_ PVOID Pattern, + _In_ ULONG PatternSize + ) +{ + KSMULTIPLE_ITEM * itemsHeader = nullptr; + SOUNDDETECTOR_PATTERNHEADER * patternHeader; + CONTOSO_KEYWORDCONFIGURATION * pattern; + ULONG cbRemaining = 0; + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + CKeywordDetector * keywordDetector = NULL; + + PAGED_CODE(); + + keywordSpotterCtx = GetDspKeywordSpotterContext(KeywordSpotter); + + keywordDetector = (CKeywordDetector*)keywordSpotterCtx->KeywordDetector; + + cbRemaining = PatternSize; + + // The SYSVADPROPERTY_ITEM for this property ensures the value size is at + // least sizeof KSMULTIPLE_ITEM. + RETURN_NTSTATUS_IF_TRUE(cbRemaining < sizeof(KSMULTIPLE_ITEM), STATUS_INVALID_PARAMETER); + + itemsHeader = (KSMULTIPLE_ITEM*)Pattern; + + // Verify property value is large enough to include the items + RETURN_NTSTATUS_IF_TRUE(itemsHeader->Size > cbRemaining, STATUS_INVALID_PARAMETER); + + // No items so clear the configuration. + if (itemsHeader->Count == 0) + { + keywordDetector->ResetDetector(*EventId); + } + else + { + // This sample supports only 1 pattern type. + RETURN_NTSTATUS_IF_TRUE(itemsHeader->Count > 1, STATUS_NOT_SUPPORTED); + + // Bytes remaining after the items header + cbRemaining = itemsHeader->Size - sizeof(*itemsHeader); + + // Verify the property value is large enough to include the pattern header. + RETURN_NTSTATUS_IF_TRUE(cbRemaining < sizeof(SOUNDDETECTOR_PATTERNHEADER), STATUS_INVALID_PARAMETER); + + patternHeader = (SOUNDDETECTOR_PATTERNHEADER*)(itemsHeader + 1); + + // Verify the pattern type is supported. + RETURN_NTSTATUS_IF_TRUE(patternHeader->PatternType != CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2, STATUS_NOT_SUPPORTED); + + // Verify the property value is large enough for the pattern. + RETURN_NTSTATUS_IF_TRUE(cbRemaining < patternHeader->Size, STATUS_INVALID_PARAMETER); + + // Verify the pattern is large enough. + RETURN_NTSTATUS_IF_TRUE(patternHeader->Size != sizeof(CONTOSO_KEYWORDCONFIGURATION), STATUS_INVALID_PARAMETER); + + pattern = (CONTOSO_KEYWORDCONFIGURATION*)(patternHeader); + + RETURN_NTSTATUS_IF_FAILED(keywordDetector->DownloadDetectorData(*EventId, pattern->ContosoDetectorConfigurationData)); + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxKeywordSpotterAssignReset( + _In_ ACXKEYWORDSPOTTER KeywordSpotter, + _In_ GUID * EventId + ) +{ + PAGED_CODE(); + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + CKeywordDetector * keywordDetector = NULL; + + keywordSpotterCtx = GetDspKeywordSpotterContext(KeywordSpotter); + + keywordDetector = (CKeywordDetector*)keywordSpotterCtx->KeywordDetector; + + RETURN_NTSTATUS_IF_FAILED(keywordDetector->ResetDetector(*EventId)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxFactoryCircuitCreateCircuitDevice( + _In_ WDFDEVICE Parent, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _Out_ WDFDEVICE * Device +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVDspLog); + + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + UNREFERENCED_PARAMETER(Factory); + + *Device = NULL; + + // Allocate a generic buffer to hold a PnP ID of this device. + // MAX_DEVICE_ID_LEN is the count of wchar in the device ID name. + C_ASSERT(NTSTRSAFE_UNICODE_STRING_MAX_CCH >= MAX_DEVICE_ID_LEN); + C_ASSERT(USHORT_MAX >= MAX_DEVICE_ID_LEN * sizeof(WCHAR)); + WCHAR *wstrBuffer = NULL; + const USHORT wstrBufferCch = MAX_DEVICE_ID_LEN; + wstrBuffer = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) WCHAR[wstrBufferCch]; + RETURN_NTSTATUS_IF_TRUE(wstrBuffer == NULL, STATUS_INSUFFICIENT_RESOURCES); + auto wstrBufferFree = scope_exit([&wstrBuffer]() { + delete[] wstrBuffer; + wstrBuffer = NULL; + }); + + RtlZeroMemory(wstrBuffer, sizeof(WCHAR) * wstrBufferCch); + + // + // Create a child audio device for this circuit. + // + PWDFDEVICE_INIT devInit = NULL; + devInit = WdfPdoInitAllocate(Parent); + RETURN_NTSTATUS_IF_TRUE(NULL == devInit, STATUS_INSUFFICIENT_RESOURCES); + auto devInitFree = scope_exit([&devInit]() { + WdfDeviceInitFree(devInit); + devInit = NULL; + }); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + + // + // Create the PnP Device ID. + // + // Retrieve the unique id of this composite. This logic uses this unique id to + // make the device id unique. Using a deterministic value for the pnp device id, guarantees + // that the KS properties associated with this audio device interface stay the same across + // reboots, even when the circuit factory is used in several ACX composites. + // + { + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID); + + ACX_OBJECTBAG_CONFIG objBagCfg; + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + objBagCfg.Handle = CircuitConfig->CompositeProperties; + objBagCfg.Flags |= AcxObjectBagConfigOpenWithHandle; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + ACXOBJECTBAG objBag = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &objBagCfg, &objBag)); + auto objBagFree = scope_exit([&objBag]() { + WdfObjectDelete(objBag); + objBag = NULL; + }); + + GUID uniqueId = { 0 }; + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveGuid(objBag, &UniqueID, &uniqueId)); + + UNICODE_STRING uniqueIdStr = { 0 }; + RETURN_NTSTATUS_IF_FAILED(RtlStringFromGUID(uniqueId, &uniqueIdStr)); + + // Init the deviceId unicode string. + UNICODE_STRING pnpDeviceId = {0}; + pnpDeviceId.Buffer = wstrBuffer; + pnpDeviceId.Length = 0; + pnpDeviceId.MaximumLength = (USHORT)(sizeof(WCHAR) * wstrBufferCch); + + status = RtlUnicodeStringPrintf(&pnpDeviceId, CAPTURE_DEVICE_ID_STR, &uniqueIdStr); + + RtlFreeUnicodeString(&uniqueIdStr); + + RETURN_NTSTATUS_IF_FAILED(status); + + // This is the device ID and the first H/W ID. + // This ID is used to create a unique audio device interface. + // Note that this ID is NOT the match with this driver's INF. + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(devInit, &pnpDeviceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &pnpDeviceId)); + } + + // This H/W ID is the match with this driver's INF. + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &CaptureHardwareId)); + + /* + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddCompatibleID(devInit, &CaptureCompatibleId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(devInit, &CaptureInstanceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignContainerID(devInit, &CaptureContainerId)); + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(devInit, + &CaptureDeviceLocation, + &CaptureDeviceLocation, + 0x409)); + */ + + WdfPdoInitSetDefaultLocale(devInit, 0x409); + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + devInitCfg.Flags |= AcxDeviceInitConfigRawDevice; + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(devInit, &devInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = DspC_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = DspC_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = DspC_EvtDeviceSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(devInit, &pnpPowerCallbacks); + + // + // Specify a context for this capture device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_CAPTURE_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = DspC_EvtDeviceContextCleanup; + attributes.ExecutionLevel = WdfExecutionLevelPassive; + + WDFDEVICE device; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&devInit, &attributes, &device)); + devInitFree.release(); + + // + // Init capture's device context. + // + PDSP_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(device); + ASSERT(devCtx != NULL); + + // + // Set device capabilities. + // + { + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + + pnpCaps.SurpriseRemovalOK = WdfTrue; + pnpCaps.UniqueID = WdfFalse; + + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + } + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + *Device = device; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS DspC_CreateKeywordSpotterElement( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _Out_ ACXKEYWORDSPOTTER * Element +) +{ + WDF_OBJECT_ATTRIBUTES attributes; + ACX_KEYWORDSPOTTER_CALLBACKS keywordSpotterCallbacks; + ACX_KEYWORDSPOTTER_CONFIG keywordSpotterCfg; + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + ACX_PNPEVENT_CONFIG keywordEventCfg; + ACXPNPEVENT keywordEvent; + + PAGED_CODE(); + + ACX_KEYWORDSPOTTER_CALLBACKS_INIT(&keywordSpotterCallbacks); + keywordSpotterCallbacks.EvtAcxKeywordSpotterRetrieveArm = DspC_EvtAcxKeywordSpotterRetrieveArm; + keywordSpotterCallbacks.EvtAcxKeywordSpotterAssignArm = DspC_EvtAcxKeywordSpotterAssignArm; + keywordSpotterCallbacks.EvtAcxKeywordSpotterAssignPatterns = DspC_EvtAcxKeywordSpotterAssignPatterns; + keywordSpotterCallbacks.EvtAcxKeywordSpotterAssignReset = DspC_EvtAcxKeywordSpotterAssignReset; + + ACX_KEYWORDSPOTTER_CONFIG_INIT(&keywordSpotterCfg); + keywordSpotterCfg.Pattern = &CONTOSO_KEYWORDCONFIGURATION_IDENTIFIER2; + keywordSpotterCfg.Callbacks = &keywordSpotterCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_KEYWORDSPOTTER_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxKeywordSpotterCreate(Circuit, &attributes, &keywordSpotterCfg, Element)); + + keywordSpotterCtx = GetDspKeywordSpotterContext(*Element); + ASSERT(keywordSpotterCtx); + + keywordSpotterCtx->KeywordDetector = (PVOID) new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CKeywordDetector(Device, Circuit, &(Pcm44100c1.WaveFormatExt)); + RETURN_NTSTATUS_IF_TRUE(keywordSpotterCtx->KeywordDetector == NULL, STATUS_INSUFFICIENT_RESOURCES); + + ACX_PNPEVENT_CONFIG_INIT(&keywordEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = *Element; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, *Element, &attributes, &keywordEventCfg, &keywordEvent)); + + keywordSpotterCtx->Event = keywordEvent; + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtAcxFactoryCircuitCreateCircuit( + _In_ WDFDEVICE Parent, + _In_ WDFDEVICE Device, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ ULONG DataPortNumber, + _In_ PSDCA_PATH_DESCRIPTORS2 PathDescriptors +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Factory); + + DrvLogEnter(g_SDCAVDspLog); + + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + DECLARE_CONST_UNICODE_STRING(circuitName, L"Microphone0"); + + // + // Init output value. + // + ASSERT(Device); + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId); + ULONG endpointId = 0; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + RETURN_NTSTATUS_IF_FAILED(RetrieveProperties(CircuitConfig, &endpointId)); + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + + ACXCIRCUIT circuit; + RETURN_NTSTATUS_IF_FAILED(CreateCaptureCircuit(CircuitInit, circuitName, Device, &circuit)); + + AcpiReader * acpiReader = GetAcpiReaderDeviceContext(Parent); + RETURN_NTSTATUS_IF_FAILED(DetermineSpecialStreamDetailsFromVendorProperties(circuit, acpiReader, CircuitConfig->CircuitProperties)); + + ASSERT(circuit != NULL); + DSP_CIRCUIT_CONTEXT *circuitCtx; + circuitCtx = GetDspCircuitContext(circuit); + ASSERT(circuitCtx); + + circuitCtx->EndpointId = endpointId; + circuitCtx->DataPortNumber = DataPortNumber; + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Add two custom circuit elements. Note that driver doesn't need to + // perform this step if it doesn't want to expose any circuit elements. + // + + // + // Create 1st custom circuit-element. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + const int numElements = 3; + ACXELEMENT elements[numElements] = {0}; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + DSP_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetDspElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom circuit-element. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetDspElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 3rd circuit-element, keyword spotter + // + RETURN_NTSTATUS_IF_FAILED(DspC_CreateKeywordSpotterElement(Device, circuit, (ACXKEYWORDSPOTTER *) &elements[2])); + circuitCtx->KeywordSpotter = (ACXKEYWORDSPOTTER)elements[2]; + + // + // Add the circuit elements + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + // PCM:44100 channel:2 24in32 + ACXDATAFORMAT formatPcm44100c2nomask; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2_24in32_nomask, circuit, Device, &formatPcm44100c2nomask)); + + // PCM:48000 channel:2 24in32 (Needed for SDCA class driver bring up) + // The No-Mask version matches what real drivers use for multi-channel capture + ACXDATAFORMAT formatPcm48000c2nomask; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2_24in32_nomask, circuit, Device, &formatPcm48000c2nomask)); + + // PCM:16000 channel:4 - this is used solely for the KeywordSpotterPin + // The No-Mask version matches what real drivers use for multi-channel capture + ACXDATAFORMAT formatPcm16000c4nomask; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm16000c4nomask, circuit, Device, &formatPcm16000c4nomask)); + + /////////////////////////////////////////////////////////// + // + // Create capture pin. AcxCircuit creates the other pin by default. + // + ACXPIN pin; + ACX_PIN_CALLBACKS pinCallbacks; + + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = DspC_EvtAcxPinSetDataFormat; + + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSource, + circuit, + AcxPinCommunicationSink, + &KSCATEGORY_AUDIO, + &pinCallbacks, + DSPC_MAX_OUTPUT_SYSTEM_STREAMS, + false, + &pin)); + ASSERT(pin != NULL); + + DSP_PIN_CONTEXT* pinCtx; + pinCtx = GetDspPinContext(pin); + ASSERT(pinCtx); + pinCtx->CapturePinType = DspCapturePinTypeHost; + + // + // Don't add any supported formats here, those will be added when this circuit + // connects to the downstream circuit + // + + // + // Add capture pin, using default pin id (0) + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create keyword streaming pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = DspC_EvtAcxPinSetDataFormat; + + + pin = NULL; + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSource, + circuit, + AcxPinCommunicationSink, + &KSNODETYPE_AUDIO_KEYWORDDETECTOR, + &pinCallbacks, + DSPC_MAX_OUTPUT_KEYWORDDETECTOR_STREAMS, + true, + &pin)); + + ASSERT(pin != NULL); + pinCtx = GetDspPinContext(pin); + ASSERT(pinCtx); + pinCtx->CapturePinType = DspCapturePinTypeKeyword; + + // + // Add our supported formats to the raw mode for the circuit + // + ACXDATAFORMATLIST formatList = AcxPinGetRawDataFormatList(pin); + RETURN_NTSTATUS_IF_TRUE(NULL == formatList, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm16000c4nomask)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create bridge pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinConnected = DspC_EvtPinConnected; + pinCallbacks.EvtAcxPinDisconnected = DspC_EvtPinDisconnected; + + pin = NULL; + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSink, + circuit, + AcxPinCommunicationNone, + &KSCATEGORY_AUDIO, + &pinCallbacks, + 0, // max streams. + false, + &pin)); + + ASSERT(pin != NULL); + pinCtx = GetDspPinContext(pin); + ASSERT(pinCtx); + pinCtx->CapturePinType = DspCapturePinTypeBridge; + + // + // Add a stream BRIDGE. + // + + ACX_STREAM_BRIDGE_CONFIG streamCfg; + ACX_STREAM_BRIDGE_CONFIG_INIT(&streamCfg); + RETURN_NTSTATUS_IF_FAILED(CreateStreamBridge(streamCfg, circuit, pin, pinCtx, DataPortNumber, endpointId, PathDescriptors, false)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + RETURN_NTSTATUS_IF_FAILED(ConnectCaptureCircuitElements(3, elements, circuit)); + + // + // Store the circuit handle in the capture device context. + // + PDSP_CAPTURE_DEVICE_CONTEXT captureDevCtx = NULL; + captureDevCtx = GetCaptureDeviceContext(Device); + ASSERT(captureDevCtx); + captureDevCtx->Circuit = circuit; + captureDevCtx->FirstTimePrepareHardware = TRUE; + + return status; +} + +// +// This callback is called when the Circuit bridge pin is connected to +// bridge pin of another circuit. +// +// This will happen when the composite circuit is fully initialized. +// From this point onwards the TargetCircuit can be used to send +// KSPROPERTY requests +// +// params: +// TargetCircuit - ACX wrapper for WDFIOTARGET for the connected circuit +// TargetPinId - The pin on the connected circuit. This can be used to +// send pin specific KSPROPERTY requests. +// +PAGED_CODE_SEG +VOID +DspC_EvtPinConnected ( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId + ) +{ + PAGED_CODE(); + + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(Pin); + pinCtx->TargetCircuit = TargetCircuit; + pinCtx->TargetPinId = TargetPinId; + + // For this sample driver, we're only adding formats to the host pin that the downstream + // pin supports. For a real DSP driver, the AUDIO_SIGNALPROCESSINGMODE_RAW data format list + // would probably include all the downstream formats, but the _DEFAULT and possibly _SPEECH + // or _COMMUNICATIONS modes would contain different formats. + // As an example, a Microphone Array's _RAW mode formats should match the channel count of the + // number of microphones in the array, whereas the _DEFAULT mode formats would be the processed + // stream in Stereo. + NTSTATUS status; + ACXPIN hostPin = AcxCircuitGetPinById(AcxPinGetCircuit(Pin), DspCapturePinTypeHost); + status = ReplicateFormatsForPin(hostPin, TargetCircuit, TargetPinId); + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVDspLog, FLAG_STREAM, L"Failed to replicate downstream formats to host pin, %!STATUS!", + status); + } + + // The ACX Framework will maintain the TargetCircuit until after it's called EvtPinDisconnect. +} + +// +// This callback is called when the Circuit bridge pin is disconnected +// from the bridge pin of another circuit. +// +// This will happen when the composite circuit is deinitialized. +// From this point onwards the TargetCircuit cannnot be used to send +// KSPROPERTY requests. +// TargetCircuit should only be used to access the attached context. +// +// params: +// TargetCircuit - ACX wrapper for WDFIOTARGET for the connected circuit +// TargetPinId - The pin on the connected circuit. +// +PAGED_CODE_SEG +VOID +DspC_EvtPinDisconnected ( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(TargetPinId); + UNREFERENCED_PARAMETER(TargetCircuit); + + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(Pin); + + if (pinCtx->TargetCircuit) + { + // After calling EvtPinDisconnected, the ACX framework will clean up + // the TargetCircuit. + pinCtx->TargetCircuit = NULL; + pinCtx->TargetPinId = (ULONG)(-1); + } +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVDspLog); + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PDSP_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + if (!devCtx->FirstTimePrepareHardware) + { + // + // This is a rebalance. Validate the circuit resources and + // if needed, delete and re-create the circuit. + // The sample driver doens't use resources, thus the existing + // circuits are kept. + // + status = STATUS_SUCCESS; + return status; + } + + // + // Set child's power policy. + // + RETURN_NTSTATUS_IF_FAILED(DspC_SetPowerPolicy(Device)); + + // + // Add circuit to child's list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Circuit)); + + // + // Keep track this is not the first time this callback was called. + // + devCtx->FirstTimePrepareHardware = FALSE; + + DrvLogExit(g_SDCAVDspLog); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + DrvLogEnter(g_SDCAVDspLog); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PDSP_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + DrvLogExit(g_SDCAVDspLog); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS DspC_EvtDeviceSelfManagedIoInit( + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + + In this callback, the driver does one-time init of self-managed I/O data. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + PDSP_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + return STATUS_SUCCESS; +} + +#pragma code_seg() +VOID DspC_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + WDFDEVICE device; + PDSP_CAPTURE_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetCaptureDeviceContext(device); + ASSERT(devCtx != NULL); + + // only clean up the circuit if it was + // successfully created, else it'll crash + if (devCtx->Circuit != NULL) + { + DspC_CircuitCleanup(devCtx->Circuit); + devCtx->Circuit = NULL; + } +} + +#pragma code_seg() +VOID +DspC_EvtCircuitContextCleanup( + _In_ WDFOBJECT Circuit + ) +/*++ + +Routine Description: + + In this callback, it cleans up circuit context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + PDSP_CIRCUIT_CONTEXT circuitCtx; + + circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx != NULL); + + // clean up the path context information in case it wasn't cleaned up + // by pin disconnection. + circuitCtx->SpecialStreamAvailablePaths = 0; + + for(ULONG i = (UINT) SpecialStreamTypeUltrasoundRender; i < (UINT) SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors[i]); + circuitCtx->SpecialStreamPathDescriptors[i] = nullptr; + } + } + + for (ULONG i = (UINT)SpecialStreamTypeUltrasoundRender; i < (UINT)SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors2[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors2[i]); + circuitCtx->SpecialStreamPathDescriptors2[i] = nullptr; + } + } + + if (circuitCtx->SpecialStreamTargetCircuit) + { + WdfObjectDereferenceWithTag(circuitCtx->SpecialStreamTargetCircuit, (PVOID)DRIVER_TAG); + circuitCtx->SpecialStreamTargetCircuit = nullptr; + } + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Circuit Cleanup %p", Circuit); +} + +#pragma code_seg() +_Use_decl_annotations_ +NTSTATUS DspC_EvtCircuitPowerUp ( + WDFDEVICE, + ACXCIRCUIT, + WDF_POWER_DEVICE_STATE +) +{ + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +NTSTATUS DspC_EvtCircuitPowerDown ( + WDFDEVICE, + ACXCIRCUIT, + WDF_POWER_DEVICE_STATE +) +{ + PAGED_CODE(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS DspC_EvtCircuitCompositeCircuitInitialize( + WDFDEVICE, + ACXCIRCUIT, + ACXOBJECTBAG +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS DspC_EvtCircuitCompositeInitialize( + WDFDEVICE, + ACXCIRCUIT, + ACXOBJECTBAG +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + return status; +} + +PAGED_CODE_SEG +VOID DspC_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + // + // Just give the request back to ACX. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +DspC_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + DrvLogEnter(g_SDCAVDspLog); + + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN kwsStream = FALSE; + + DSP_PIN_CONTEXT * pinCtx; + pinCtx = GetDspPinContext(Pin); + ASSERT(pinCtx != NULL); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + { + ASSERT(pinCtx->CurrentStreamsCount != (ULONG)-1); + RETURN_NTSTATUS_IF_TRUE_MSG( + pinCtx->CurrentStreamsCount >= pinCtx->MaxStreams, + STATUS_INSUFFICIENT_RESOURCES, + L"ACXCIRCUIT %p ACXPIN %p cannot create another ACXSTREAM, max count is %d, %!STATUS!", + Circuit, Pin, pinCtx->MaxStreams, status); + } +#endif + + // + // Request a Vendor-Specific property from the Controller + // + Dsp_SendVendorSpecificProperties( + Device, + Circuit, + FALSE); + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + DspC_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = Dsp_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = Dsp_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = Dsp_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = Dsp_EvtStreamPause; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS rtCallbacks; + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = Dsp_EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = Dsp_EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = Dsp_EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamGetCapturePacket = DspC_EvtStreamGetCapturePacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = Dsp_EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = Dsp_EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_STREAM_CONTEXT); + attributes.EvtDestroyCallback = Dsp_EvtStreamContextDestroy; + attributes.EvtCleanupCallback = Dsp_EvtStreamContextCleanup; + + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + DSP_STREAM_CONTEXT* streamCtx; + streamCtx = GetDspStreamContext(stream); + ASSERT(streamCtx); + + streamCtx->CapturePinType = pinCtx->CapturePinType; + + DSP_CIRCUIT_CONTEXT * circuitCtx; + circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx != NULL); + + CCaptureStreamEngine *streamEngine = NULL; + + if (pinCtx->CapturePinType == DspCapturePinTypeKeyword) + { + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + keywordSpotterCtx = GetDspKeywordSpotterContext(circuitCtx->KeywordSpotter); + ASSERT(keywordSpotterCtx); + + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CBufferedCaptureStreamEngine(stream, StreamFormat, (CKeywordDetector *) keywordSpotterCtx->KeywordDetector); + kwsStream = TRUE; + } + else + { + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CCaptureStreamEngine(stream, StreamFormat); + } + + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES); + + streamCtx->StreamEngine = (PVOID)streamEngine; + streamEngine = NULL; + + // + // Post stream creation initialization. + // + + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXELEMENT elements[2] = { 0 }; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + DSP_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetDspElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetDspElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + ACXPIN bridgePin = AcxCircuitGetPinById(Circuit, (ULONG)DspCapturePinTypeBridge); + RETURN_NTSTATUS_IF_TRUE(bridgePin == NULL, STATUS_UNSUCCESSFUL); + PDSP_PIN_CONTEXT bridgePinCtx = GetDspPinContext(bridgePin); + if (!kwsStream) + { + // KWS Streams are handled in the DSP. Only add non-KWS streams to the StreamBridge, which + // will forward the stream creation to downlevel circuits (i.e. Xu and Codec drivers) + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeAddStream(bridgePinCtx->HostStreamBridge, stream)); + } + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + { + ASSERT(pinCtx->CurrentStreamsCount != (ULONG)-1); + InterlockedIncrement(PLONG(&pinCtx->CurrentStreamsCount)); + streamCtx->StreamIsCounted = TRUE; + } +#endif + + streamCtx->Pin = Pin; + WdfObjectReferenceWithTag(Pin, (PVOID)DRIVER_TAG); + + return status; +} + +PAGED_CODE_SEG +VOID +DspC_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACX_REQUEST_PARAMETERS params; + ULONG_PTR outDataCb = 0; + PDSP_STREAM_CONTEXT streamCtx; + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + streamCtx = GetDspStreamContext(Object); + if (streamCtx && streamCtx->CapturePinType == DspCapturePinTypeKeyword) + { + if (IsEqualGUID(params.Parameters.Property.Set, KSPROPSETID_RtAudio) && + params.Parameters.Property.Id == KSPROPERTY_RTAUDIO_PACKETVREGISTER) + { + status = STATUS_NOT_SUPPORTED; + outDataCb = 0; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"DSP Capture Stream for Keyword Overriding PACKETVREGISTER request, %!STATUS!", + status); + + WdfRequestCompleteWithInformation(Request, status, outDataCb); + return; + } + } + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +DspC_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + + PAGED_CODE(); + + // + // Init the idle policy structure. + // + //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = 10000; // 10-sec + + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DspC_CircuitCleanup( + _In_ ACXCIRCUIT Circuit + ) +{ + PDSP_CIRCUIT_CONTEXT circuitCtx; + PDSP_KEYWORDSPOTTER_CONTEXT keywordSpotterCtx; + CKeywordDetector * keywordDetector = NULL; + + PAGED_CODE(); + + // Remove the static capture circuit + circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx != NULL); + + keywordSpotterCtx = GetDspKeywordSpotterContext(circuitCtx->KeywordSpotter); + ASSERT(keywordSpotterCtx != NULL); + + keywordDetector = (CKeywordDetector*)keywordSpotterCtx->KeywordDetector; + keywordSpotterCtx->KeywordDetector = NULL; + delete keywordDetector; + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +DspC_EvtAcxPinSetDataFormat( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +#pragma code_seg() +VOID +DspC_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin +) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(WdfPin); + + if (pinCtx->TargetCircuit) + { + WdfObjectDereferenceWithTag(pinCtx->TargetCircuit, (PVOID)DRIVER_TAG); + + pinCtx->TargetCircuit = NULL; + pinCtx->TargetPinId = (ULONG)(-1); + } +} + +PAGED_CODE_SEG +NTSTATUS +DspC_EvtStreamGetCapturePacket( + _In_ ACXSTREAM Stream, + _Out_ ULONG* LastCapturePacket, + _Out_ ULONGLONG* QPCPacketStart, + _Out_ BOOLEAN* MoreData +) +{ + PDSP_STREAM_CONTEXT ctx; + CCaptureStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = static_cast<CCaptureStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetCapturePacket(LastCapturePacket, QPCPacketStart, MoreData); +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/circuitstream.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/circuitstream.cpp new file mode 100644 index 00000000..d7d500c2 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/circuitstream.cpp @@ -0,0 +1,820 @@ +/*++ + + 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: + + circuitstream.cpp + +Abstract: + + Circuit Stream callbacks + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" + +#pragma code_seg() +VOID +Dsp_EvtStreamContextDestroy( + _In_ WDFOBJECT Object +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + ctx = GetDspStreamContext((ACXSTREAM)Object); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + ctx->StreamEngine = NULL; + delete streamEngine; +} + +PAGED_CODE_SEG +VOID +Dsp_EvtStreamContextCleanup( + _In_ WDFOBJECT Object +) +{ + PDSP_STREAM_CONTEXT streamCtx = GetDspStreamContext((ACXSTREAM)Object); + + PAGED_CODE(); + + if (streamCtx->Pin != NULL) + { +#ifdef ACX_WORKAROUND_ACXPIN_01 + + PDSP_PIN_CONTEXT pinCtx = GetDspPinContext(streamCtx->Pin); + + if (streamCtx->StreamIsCounted) + { + ASSERT(pinCtx->CurrentStreamsCount > 0); + InterlockedDecrement(PLONG(&pinCtx->CurrentStreamsCount)); + streamCtx->StreamIsCounted = FALSE; + } +#endif // ACX_WORKAROUND_ACXPIN_01 + + WdfObjectDereferenceWithTag(streamCtx->Pin, (PVOID)DRIVER_TAG); + streamCtx->Pin = NULL; + } + + if (streamCtx->SpecialStreamTargetCircuit) + { + WdfObjectDereferenceWithTag(streamCtx->SpecialStreamTargetCircuit, (PVOID)DRIVER_TAG); + streamCtx->SpecialStreamTargetCircuit = nullptr; + } +} + +#ifdef ACX_WORKAROUND_ACXPIN_01 +PAGED_CODE_SEG +VOID +Dsp_EvtStreamGetStreamCountRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is a preprocess routine. + +--*/ +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACXCIRCUIT circuit = (ACXCIRCUIT)Object; + ULONG_PTR outDataCb = 0; + ACX_REQUEST_PARAMETERS params; + + UNREFERENCED_PARAMETER(DriverContext); + + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + // + // Make sure this is a pin property request. + // + if ((params.Type != AcxRequestTypeProperty) || + (params.Parameters.Property.ItemType != AcxItemTypePin)) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + // + // Handle only the 'get' verb. + // + if (params.Parameters.Property.Verb == AcxPropertyVerbGet) + { + ACXPIN pin = NULL; + KSPIN_CINSTANCES * value = NULL; + ULONG valueCb = 0; + ULONG minSize = sizeof(KSPIN_CINSTANCES); + + value = (KSPIN_CINSTANCES*)params.Parameters.Property.Value; + valueCb = params.Parameters.Property.ValueCb; + + // + // Get the associated pin object. + // + pin = AcxCircuitGetPinById(circuit, params.Parameters.Property.ItemId); + if (pin == NULL) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + if (valueCb == 0) + { + outDataCb = minSize; + status = STATUS_BUFFER_OVERFLOW; + goto exit; + } + else if (valueCb < minSize) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + else + { + PDSP_PIN_CONTEXT pinCtx = GetDspPinContext(pin); + value->PossibleCount = pinCtx->MaxStreams; + value->CurrentCount = pinCtx->CurrentStreamsCount; // Aligned dword reads are atomic. + outDataCb = minSize; + } + } + else + { + // + // Just give it back to ACX. After this call the request is gone. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); + Request = NULL; + goto exit; + } + + status = STATUS_SUCCESS; + +exit: + if (Request != NULL) + { + WdfRequestCompleteWithInformation(Request, status, outDataCb); + } +} +#endif // ACX_WORKAROUND_ACXPIN_01 + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_02 +PAGED_CODE_SEG +VOID +Dsp_EvtStreamProposeDataFormatRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + { + ACXCIRCUIT circuit = (ACXCIRCUIT)Object; + ACXPIN pin = NULL; + PDSP_PIN_CONTEXT pinCtx = NULL; + + ACX_REQUEST_PARAMETERS params; + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + if ((params.Type != AcxRequestTypeProperty) || + (params.Parameters.Property.ItemType != AcxItemTypePin) || + (params.Parameters.Property.Verb != AcxPropertyVerbSet)) + { + goto forward_request; + } + + // + // Get the associated pin object. + // + pin = AcxCircuitGetPinById(circuit, params.Parameters.Property.ItemId); + if (pin == NULL) + { + goto forward_request; + } + + // + // Check if this is the offload pin. + // + pinCtx = GetDspPinContext(pin); + if (!pinCtx || (pinCtx->PinType != DspPinTypeOffload)) + { + goto forward_request; + } + + // + // This is an offload pin, check # of streams. + // + if (pinCtx->CurrentStreamsCount >= pinCtx->MaxStreams) + { + // Cannot create any more streams, error out. + WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); + return; + } + } + + // + // Just give it back to ACX. After this call the request is gone. + // +forward_request: + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} +#endif // ACX_WORKAROUND_ACXPIN_02 + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->GetHWLatency(FifoSize, Delay); +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamAllocateRtPackets( + _In_ ACXSTREAM Stream, + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET *Packets +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AllocateRtPackets(PacketCount, PacketSize, Packets); +} + +PAGED_CODE_SEG +VOID +Dsp_EvtStreamFreeRtPackets( + _In_ ACXSTREAM Stream, + _In_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->FreeRtPackets(Packets, PacketCount); +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_PrepareSpecialStreamForStream( + _In_ ACXSTREAM Stream, + _In_ SDCA_SPECIALSTREAM_TYPE SpecialStreamType, + _In_ ULONG FunctionBitMask + ) +{ + NTSTATUS status = STATUS_SUCCESS; + SDCA_PATH specialStreamPath = SdcaPathFromSpecialStreamType(SpecialStreamType); + PDSP_STREAM_CONTEXT ctx = GetDspStreamContext(Stream); + ACXCIRCUIT circuit = AcxPinGetCircuit(ctx->Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + PSDCA_PATH_DESCRIPTORS pathDescriptors = nullptr; + BOOLEAN activeStreamCountIncremented = FALSE; + + PAGED_CODE(); + + if (circuitCtx->SpecialStreamAvailablePaths & specialStreamPath && + !ctx->SpecialStreamInUse[SpecialStreamType]) + { + ULONG streamCount = InterlockedIncrement(PLONG(&(circuitCtx->SpecialStreamActive[SpecialStreamType]))); + activeStreamCountIncremented = TRUE; + + if (1 == streamCount) + { + // TODO: The above ensures that the global special stream usage counts are protected, however if a special stream + // were destroyed at near the same time as another one created, then there could be a timing issue between the + // timing of this call to create the path and the timing of the ReleaseHardware call destroying the path. + // i.e. ReleaseHardware performs an interlocked decrement to 0 and then a context switch. PrepareHardware runs and does an interlocked increment + // back to 1, and performs the CreatePath call as it appears to be the first and the path is not created. + // Then, ReleaseHardware resumes and calls DestroyPath. + // So, can a PrepareHardware and a ReleaseHardware for two different streams on the same pin, happen at the same time? + + // Sample driver uses audio composition data to determine if it is going to use pathdescriptor2 or pathdescriptor + // to prepare special stream. Audio composition will also provide the entire pathdescriptor2 to be used. + if (circuitCtx->SpecialStreamPathDescriptors2[SpecialStreamType]) + { + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + ctx->SpecialStreamTargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_CREATE_PATH2, + AcxPropertyVerbSet, + nullptr, 0, + circuitCtx->SpecialStreamPathDescriptors2[SpecialStreamType], + circuitCtx->SpecialStreamPathDescriptors2[SpecialStreamType]->Size, + nullptr); + if (!NT_SUCCESS(status)) + { + goto exit; + } + } + else + { + // for simplicity, we take a copy of the entire path descriptors returned from downstream, and then adjust that copy + // to have the requested data port & format, leaving the remaining, if there are any, unused. + pathDescriptors = (PSDCA_PATH_DESCRIPTORS)ExAllocatePool2(POOL_FLAG_NON_PAGED, circuitCtx->SpecialStreamPathDescriptors[SpecialStreamType]->Size, DRIVER_TAG); + if (pathDescriptors == nullptr) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto exit; + } + RtlCopyMemory(pathDescriptors, circuitCtx->SpecialStreamPathDescriptors[SpecialStreamType], circuitCtx->SpecialStreamPathDescriptors[SpecialStreamType]->Size); + + // walk the descriptors and adjust each entry to have 1 format, preferred one if available, + // and a single data port. The remaining entries beyond the first are there and accounted for + // by the size, but are unused. + PSDCA_PATH_DESCRIPTOR currentDescriptor = (PSDCA_PATH_DESCRIPTOR)(pathDescriptors + 1); + // In some cases we will only use some of the functions; targetDescriptor will receive the next descriptor if we skip any + PSDCA_PATH_DESCRIPTOR targetDescriptor = currentDescriptor; + ULONG descriptorCount = 0; + for (ULONG j = 0; j < pathDescriptors->DescriptorCount; j++) + { + PSDCA_PATH_DESCRIPTOR nextDescriptor = (PSDCA_PATH_DESCRIPTOR)(((BYTE*)currentDescriptor) + currentDescriptor->Size); + + if (((1 << currentDescriptor->FunctionInformationId) & FunctionBitMask) == 0) + { + // This audio function isn't included in what should be started + currentDescriptor = nextDescriptor; + continue; + } + + if (currentDescriptor != targetDescriptor) + { + RtlCopyMemory(targetDescriptor, currentDescriptor, currentDescriptor->Size); + } + + PSDCA_PATH_DESCRIPTOR nextTargetDescriptor = (PSDCA_PATH_DESCRIPTOR)(((BYTE*)targetDescriptor) + targetDescriptor->Size); + + for (ULONG i = 0; i < targetDescriptor->FormatCount; i++) + { + if (48000 == targetDescriptor->Formats[i].Format.nSamplesPerSec) + { + RtlCopyMemory(&(targetDescriptor->Formats[0]), &(targetDescriptor->Formats[i]), sizeof(targetDescriptor->Formats[0])); + break; + } + } + + targetDescriptor->FormatCount = min(targetDescriptor->FormatCount, 1); + targetDescriptor->DataPortCount = min(targetDescriptor->DataPortCount, 1); + + targetDescriptor = nextTargetDescriptor; + currentDescriptor = nextDescriptor; + + ++descriptorCount; + } + + if (descriptorCount == 0) + { + // No target functions were chosen. + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + pathDescriptors->DescriptorCount = descriptorCount; + + // A real DSP driver would choose a suitable EndpointID. This is a placeholder. + pathDescriptors->EndpointId = 0xaa; + + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + ctx->SpecialStreamTargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_CREATE_PATH, + AcxPropertyVerbSet, + nullptr, 0, + pathDescriptors, pathDescriptors->Size, + nullptr); + if (!NT_SUCCESS(status)) + { + goto exit; + } + } + } + + // If we succeeded in creating the path, set the tracking variable for the stream type + ctx->SpecialStreamInUse[SpecialStreamType] = TRUE; + } + +exit: + if (!NT_SUCCESS(status) && activeStreamCountIncremented) + { + // if we failed to create it, this call is going to fail, undo the circuit context tracking + InterlockedDecrement(PLONG(&(circuitCtx->SpecialStreamActive[SpecialStreamType]))); + } + + if (pathDescriptors) + { + ExFreePool(pathDescriptors); + pathDescriptors = nullptr; + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_ReleaseSpecialStreamsForStream( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx = GetDspStreamContext(Stream); + ACXCIRCUIT circuit = AcxPinGetCircuit(ctx->Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + + PAGED_CODE(); + + for (ULONG streamType = 0; streamType < ARRAYSIZE(ctx->SpecialStreamInUse); ++streamType) + { + if (!ctx->SpecialStreamInUse[streamType]) + { + continue; + } + + // As the special stream hardware is potentially shared across multiple streams, + // special stream state is tracked in the circuit context. + // Decrement shared circuit context tracking to indicate that this stream is no longer using this special stream path + ULONG streamCount = InterlockedDecrement(PLONG(&(circuitCtx->SpecialStreamActive[streamType]))); + + // if this was the last user of it, destroy the special stream path + if (0 == streamCount) + { + SDCA_PATH path = SdcaPathFromSpecialStreamType((SDCA_SPECIALSTREAM_TYPE)streamType); + NTSTATUS sendStatus; + + sendStatus = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + ctx->SpecialStreamTargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_DESTROY_PATH, + AcxPropertyVerbSet, + nullptr, 0, + &path, sizeof(path), + nullptr); + + status = !NT_SUCCESS(status) ? status : sendStatus; + } + + // if the path has been destroyed, it also cannot be running, + // so update the special stream state for both. + ctx->SpecialStreamInUse[streamType] = FALSE; + ctx->SpecialStreamRunning[streamType] = FALSE; + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + // prepare the stream engine hardware + status = streamEngine->PrepareHardware(); + + // For a host or offload pin, start the Sense stream + // if it isn't already running + if (NT_SUCCESS(status) && + (DspPinTypeHost == ctx->PinType || DspPinTypeOffload == ctx->PinType)) + { + status = Dsp_PrepareSpecialStreamForStream(Stream, SpecialStreamTypeIvSense); + } + + // If this is loopback, we may be able to use reference + // stream hardware, check + if (NT_SUCCESS(status) && + DspPinTypeLoopback == ctx->PinType) + { + // for sample purposes, we're using the same stream engine for loopback with + // reference stream as without. The only difference is whether the special stream + // properties are being used to create, destroy, start, and stop the reference stream + // hardware when the loopback stream is used. + + status = Dsp_PrepareSpecialStreamForStream(Stream, SpecialStreamTypeReferenceStream); + } + + if (!NT_SUCCESS(status)) + { + (void)Dsp_ReleaseSpecialStreamsForStream(Stream); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + status = Dsp_ReleaseSpecialStreamsForStream(Stream); + + NTSTATUS engineStatus = streamEngine->ReleaseHardware(); + + return NT_SUCCESS(engineStatus)?status:engineStatus; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_StopSpecialStreamsForStream( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx = GetDspStreamContext(Stream); + ACXCIRCUIT circuit = AcxPinGetCircuit(ctx->Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + + PAGED_CODE(); + + for (ULONG streamType = 0; streamType < ARRAYSIZE(ctx->SpecialStreamInUse); ++streamType) + { + if (ctx->SpecialStreamRunning[streamType]) + { + // As the special stream hardware is potentially shared across multiple streams, + // special stream state is tracked in the circuit context. + // Decrement shared circuit context tracking to indicate that this stream is no longer running + ULONG streamCount = InterlockedDecrement(PLONG(&(circuitCtx->SpecialStreamRunning[streamType]))); + + // if this was the last stream using it, stop the path + if (0 == streamCount) + { + SDCA_PATH path = SdcaPathFromSpecialStreamType((SDCA_SPECIALSTREAM_TYPE)streamType); + NTSTATUS sendStatus; + + sendStatus = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + ctx->SpecialStreamTargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_STOP_PATH, + AcxPropertyVerbSet, + nullptr, 0, + &path, sizeof(path), + nullptr); + + status = !NT_SUCCESS(status) ? status : sendStatus; + } + + // update special stream state + ctx->SpecialStreamRunning[streamType] = FALSE; + } + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_StartSpecialStreamsForStream( + _In_ ACXSTREAM Stream + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx = GetDspStreamContext(Stream); + ACXCIRCUIT circuit = AcxPinGetCircuit(ctx->Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + + PAGED_CODE(); + + for (ULONG streamType = 0; streamType < ARRAYSIZE(ctx->SpecialStreamInUse); ++streamType) + { + if (ctx->SpecialStreamInUse[streamType] && + !ctx->SpecialStreamRunning[streamType]) + { + // As the special stream hardware is potentially shared across multiple streams, + // special stream state is tracked in the circuit context. + // Increment shared circuit context tracking to indicate that this stream is running + ULONG streamCount = InterlockedIncrement(PLONG(&(circuitCtx->SpecialStreamRunning[streamType]))); + + // if we are the first to use it, start the path + if (1 == streamCount) + { + SDCA_PATH path = SdcaPathFromSpecialStreamType((SDCA_SPECIALSTREAM_TYPE)streamType); + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + ctx->SpecialStreamTargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_START_PATH, + AcxPropertyVerbSet, + nullptr, 0, + &path, sizeof(path), + nullptr); + } + + // if we succeeded in starting the path, update set our tracking + if (NT_SUCCESS(status)) + { + ctx->SpecialStreamRunning[streamType] = TRUE; + } + else + { + // if we failed to set the state, so clear the state tracking + InterlockedDecrement(PLONG(&(circuitCtx->SpecialStreamRunning[streamType]))); + + // If we failed, exit early so we can clean up + break; + } + } + } + + if (!NT_SUCCESS(status)) + { + // If this stream has more than one special stream, it's possible we failed after starting + // one or more special streams. As such, make sure all streams are stopped. + (void)Dsp_StopSpecialStreamsForStream(Stream); + } + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamRun( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + status = streamEngine->Run(); + + // if we're using reference stream and aren't already running, + // set our state to running. + if (NT_SUCCESS(status)) + { + status = Dsp_StartSpecialStreamsForStream(Stream); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamPause( + _In_ ACXSTREAM Stream +) +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + // if any special streams are running (which can only happen if they're being used) + // and we're pausing, update tracking + status = Dsp_StopSpecialStreamsForStream(Stream); + + NTSTATUS engineStatus = streamEngine->Pause(); + + return NT_SUCCESS(engineStatus)?status:engineStatus; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AssignDrmContentId(DrmContentId, DrmRights); +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamGetCurrentPacket( + _In_ ACXSTREAM Stream, + _Out_ PULONG CurrentPacket +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetCurrentPacket(CurrentPacket); +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtStreamGetPresentationPosition( + _In_ ACXSTREAM Stream, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + PDSP_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + return streamEngine->GetPresentationPosition(PositionInBlocks, QPCPosition); +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/device.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/device.cpp new file mode 100644 index 00000000..36c0e95a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/device.cpp @@ -0,0 +1,1631 @@ +/*++ + + 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: + + Device.cpp + +Abstract: + + Plug and Play module. This file contains routines to handle pnp requests. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "streamengine.h" +#include "AcpiReader.h" +#include <devguid.h> + + +#ifndef __INTELLISENSE__ +#include "device.tmh" +#endif + +using namespace ACPIREADER; + +UNICODE_STRING g_RegistryPath = {0}; // This is used to store the registry settings path for the driver + +DEFINE_GUID(DSP_CIRCUIT_RENDER_GUID, +0x9e4f4968, 0x4dd0, 0x4aaa, 0x93, 0x0e, 0xcd, 0xc4, 0xe2, 0x8f, 0xf5, 0xb1); + +DEFINE_GUID(DSP_CIRCUIT_CAPTURE_GUID, +0xe813215a, 0xfb5e, 0x4c9d, 0xb8, 0x99, 0x91, 0x18, 0x56, 0xb6, 0xde, 0x81); + +// {17F5B19F-C2C7-4B53-AFB9-49A0283D0DCE} +DEFINE_GUID(DSP_CIRCUIT_SPEAKER_GUID, + 0x17f5b19f, 0xc2c7, 0x4b53, 0xaf, 0xb9, 0x49, 0xa0, 0x28, 0x3d, 0xd, 0xce); + +// {6F9EACF7-CD2D-4030-9E49-7CC4ADEFF192} +DEFINE_GUID(DSP_CIRCUIT_MICROPHONE_GUID, + 0x6f9eacf7, 0xcd2d, 0x4030, 0x9e, 0x49, 0x7c, 0xc4, 0xad, 0xef, 0xf1, 0x92); + +// {9B5AEA69-F6E5-4BA3-9968-37FA548F5503} +DEFINE_GUID(DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID, + 0x9b5aea69, 0xf6e5, 0x4ba3, 0x99, 0x68, 0x37, 0xfa, 0x54, 0x8f, 0x55, 0x3); + +// {3D405590-9368-4706-88E1-B69AD80C8969} +DEFINE_GUID(DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID, + 0x3d405590, 0x9368, 0x4706, 0x88, 0xe1, 0xb6, 0x9a, 0xd8, 0xc, 0x89, 0x69); + +// {4DCB0606-6415-4A36-BDC5-9B1792117DC9} +DEFINE_GUID(DSP_FACTORY_GUID, + 0x4dcb0606, 0x6415, 0x4a36, 0xbd, 0xc5, 0x9b, 0x17, 0x92, 0x11, 0x7d, 0xc9); + +DEFINE_GUID(SYSTEM_CONTAINER_GUID, +0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 +// +// Factory class method: KSMETHODSETID_AcxFactoryCircuit +// +#define STATIC_KSMETHODSETID_AcxFactoryCircuit\ + 0xc09a3089L, 0x3eee, 0x47e0, 0xb9, 0x37, 0x4a, 0x74, 0x66, 0xae, 0xed, 0x6b +DEFINE_GUIDSTRUCT("c09a3089-3eee-47e0-b937-4a7466aeed6b", KSMETHODSETID_AcxFactoryCircuit); +#define KSMETHODSETID_AcxFactoryCircuit DEFINE_GUIDNAMED(KSMETHODSETID_AcxFactoryCircuit) + +typedef enum { + KSMETHOD_ACXFACTORYCIRCUIT_ADDCIRCUIT = 1, + KSMETHOD_ACXFACTORYCIRCUIT_REMOVECIRCUIT = 2, +} KSMETHOD_ACXFACTORYCIRCUIT; +#endif // ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + +#pragma code_seg() + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +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 + +--*/ + +{ + PAGED_CODE(); + + // 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, DRIVER_TAG); + + if (g_RegistryPath.Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // ExAllocatePool2 zeros memory. + + RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_AddAudioSensorsDevice( + _In_ WDFCHILDLIST DeviceList, + _In_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, + _In_ PWDFDEVICE_INIT ChildInit + ) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + PAUDIO_SENSORS_DEVICE_CONTEXT audioSensorsDevCtx; + PDSP_DEVICE_CONTEXT dspDevCtx; + WDFDEVICE sensorsDevice = nullptr; + + WDFDEVICE Device = WdfChildListGetDevice(DeviceList); + + DECLARE_CONST_UNICODE_STRING(buffer, L"SOUNDWIRE\\AUDIOSENSORS"); + DECLARE_UNICODE_STRING_SIZE(buffer2, 128); + DECLARE_CONST_UNICODE_STRING(AudioSensorsDeviceText, L"Audio Sensors Device"); + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(IdentificationDescription); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(ChildInit, &buffer)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(ChildInit, &buffer)); + + RETURN_NTSTATUS_IF_FAILED(RtlUnicodeStringPrintf(&buffer2, L"%08x", 12345)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(ChildInit, &buffer2)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(ChildInit, &AudioSensorsDeviceText, &AudioSensorsDeviceText, 0x409)); + + WdfPdoInitSetDefaultLocale(ChildInit, 0x409); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, AUDIO_SENSORS_DEVICE_CONTEXT); + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&ChildInit, &attributes, &sensorsDevice)); + + dspDevCtx = GetDspDeviceContext(Device); + ASSERT(dspDevCtx!=NULL); + + dspDevCtx->AudioSensorsDevice = sensorsDevice; + + audioSensorsDevCtx = GetAudioSensorsDeviceContext(sensorsDevice); + ASSERT(audioSensorsDevCtx != NULL); + + // + // Set device capabilities. + // + { + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + + pnpCaps.SurpriseRemovalOK = WdfTrue; + pnpCaps.UniqueID = WdfFalse; + + WdfDeviceSetPnpCapabilities(sensorsDevice, &pnpCaps); + } + + DrvLogInfo(g_SDCAVDspLog, FLAG_INIT, "Successfully Created Audio Sensors Device."); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +Dsp_CreateChildList( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_CHILD_LIST_CONFIG config; + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER description; + PDSP_DEVICE_CONTEXT dspDevCtx; + + PAGED_CODE(); + + dspDevCtx = GetDspDeviceContext(Device); + ASSERT(dspDevCtx != NULL); + + // + // Init a new child list so that we can enumerate Audio Sensors PDO + // + WDF_CHILD_LIST_CONFIG_INIT( + &config, + sizeof(WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER), + Dsp_AddAudioSensorsDevice // callback to create a child device. + ); + + RETURN_NTSTATUS_IF_FAILED(WdfChildListCreate( + Device, + &config, + WDF_NO_OBJECT_ATTRIBUTES, + &dspDevCtx->ChildList)); + + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description, sizeof(description)); + RETURN_NTSTATUS_IF_FAILED(WdfChildListAddOrUpdateChildDescriptionAsPresent( + dspDevCtx->ChildList, + &description, + NULL)); + + DrvLogInfo(g_SDCAVDspLog, FLAG_INIT, "Successfully created new child list"); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtBusDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. All the software resources + should be allocated in this callback. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Driver); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = Dsp_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = Dsp_EvtDeviceReleaseHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + // + // Specify the type of context needed. + // Use default locking, i.e., none. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = Dsp_EvtDeviceContextCleanup; + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg)); + + // + // Create the device. + // + WDFDEVICE device = NULL; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device)); + + // + // Init Dsp's device context. + // + PDSP_DEVICE_CONTEXT devCtx; + devCtx = GetDspDeviceContext(device); + ASSERT(devCtx != NULL); + devCtx->Render = NULL; + devCtx->Capture = NULL; + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + // + // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so + // that you don't get the popup in usermode (on Win2K) when you surprise + // remove the device. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.SurpriseRemovalOK = WdfTrue; + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + + // + // Default child list is owned by ACX and can only contain PDOs that + // ACX is aware of so create new child list that will contain Audio Sensors PDO. + // + RETURN_NTSTATUS_IF_FAILED(Dsp_CreateChildList(device)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PDSP_DEVICE_CONTEXT devCtx; + devCtx = GetDspDeviceContext(Device); + ASSERT(devCtx != NULL); + + + RETURN_NTSTATUS_IF_FAILED(Dsp_SetPowerPolicy(Device)); + + RETURN_NTSTATUS_IF_FAILED(CSaveData::SetDeviceObject(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CSaveData::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(CWaveReader::InitializeWorkItems(WdfDeviceWdmGetDeviceObject(Device))); + + RETURN_NTSTATUS_IF_FAILED(AcpiReader::_CreateAndInitialize(Device, g_SDCAVDspLog, DRIVER_TAG)); + + // + // Add a circuit factory that will handle all different devices + // + if (!devCtx->Factory) + { + RETURN_NTSTATUS_IF_FAILED(Dsp_AddFactoryCircuit(Device)); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated + ) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PDSP_DEVICE_CONTEXT devCtx; + devCtx = GetDspDeviceContext(Device); + ASSERT(devCtx != NULL); + + // + // Note that we don't remove the factory circuit here (AcxDeviceRemoveFactoryCircuit). + // If the factory circuit is removed here, any circuit devices created through it could + // be destroyed without ACX knowledge resulting in a Duplicate PDO bugcheck. + // + + + CSaveData::DestroyWorkItems(); + CWaveReader::DestroyWorkItems(); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_SetPowerPolicy( + _In_ WDFDEVICE Device + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Init the idle policy structure. + // + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = 10000; // 10-sec + + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + + return status; +} + +#pragma code_seg() +VOID +Dsp_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + WDFDEVICE device; + PDSP_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetDspDeviceContext(device); + ASSERT(devCtx != NULL); + + if (devCtx->Capture) + { + DspC_CircuitCleanup(devCtx->Capture); + devCtx->Capture = NULL; + } + + if (devCtx->AudioSensorsDevice) + { + devCtx->AudioSensorsDevice = nullptr; + } +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_DetermineCircuitDetailsFromVendorProperties( + _In_ AcpiReader * Acpi, + _In_ ACXOBJECTBAG CircuitProperties, + _Out_ PGUID CircuitId, + _Out_opt_ ULONG * DataPortNumber = nullptr, + _In_ ULONG MaxPathDescriptors = 0, + _Out_opt_ PSDCA_PATH_DESCRIPTORS2 PathDescriptors = nullptr +) +{ + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(VendorPropertiesBlock); + WDFMEMORY vendorPropertiesBlock = NULL; + char* vendorPropertiesBuffer = NULL; + ULONG vendorPropertiesSize; + NTSTATUS status = STATUS_NOT_FOUND; + + PAGED_CODE(); + + if (PathDescriptors != nullptr && MaxPathDescriptors == 0) + { + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveBlob(CircuitProperties, &VendorPropertiesBlock, NULL, &vendorPropertiesBlock)); + + auto cleanup1 = scope_exit([&vendorPropertiesBlock] () + { + if (vendorPropertiesBlock != NULL) + { + WdfObjectDelete(vendorPropertiesBlock); + vendorPropertiesBlock = NULL; + } + }); + + RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED( + Acpi->GetPropertyString("acpi-vendor-config-type", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, + vendorPropertiesBlock, NULL, 0, &vendorPropertiesSize), + STATUS_BUFFER_TOO_SMALL); + + vendorPropertiesBuffer = (char*)ExAllocatePool2(POOL_FLAG_PAGED, vendorPropertiesSize, DRIVER_TAG); + + auto cleanup2 = scope_exit([&vendorPropertiesBuffer] () + { + if (vendorPropertiesBuffer != NULL) + { + ExFreePool(vendorPropertiesBuffer); + vendorPropertiesBuffer = NULL; + } + }); + + RETURN_NTSTATUS_IF_FAILED( + Acpi->GetPropertyString("acpi-vendor-config-type", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, + vendorPropertiesBlock, vendorPropertiesBuffer, vendorPropertiesSize, &vendorPropertiesSize)); + + // use ACPI methods to parse for DataPortNumber + if (DataPortNumber) + { + *DataPortNumber = 0; + } + if (PathDescriptors) + { + RtlZeroMemory(PathDescriptors, sizeof(*PathDescriptors) + (MaxPathDescriptors - 1) * sizeof(PathDescriptors->Descriptor[0])); + } + + *CircuitId = NULL_GUID; + + // This code also assumes Data Port number based on type of endpoint, which is not correct + // for real hardware. Data Port number should come from ACPI. + if (sizeof("Streaming_Speaker") <= vendorPropertiesSize && sizeof("Streaming_Speaker") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_Speaker", sizeof("Streaming_Speaker"))) + { + *CircuitId = DSP_CIRCUIT_SPEAKER_GUID; + if (DataPortNumber) + { + // Speaker connects to DP 1 + *DataPortNumber = 1; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_MicrophoneArray") <= vendorPropertiesSize && sizeof("Streaming_MicrophoneArray") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_MicrophoneArray", sizeof("Streaming_MicrophoneArray"))) + { + *CircuitId = DSP_CIRCUIT_MICROPHONE_GUID; + if (DataPortNumber) + { + // Raw capture path connects to DP 6 + *DataPortNumber = 6; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_Headphones") <= vendorPropertiesSize && sizeof("Streaming_Headphones") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_Headphones", sizeof("Streaming_Headphones"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; + if (DataPortNumber) + { + // UAJ Output uses DP 3 + *DataPortNumber = 3; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_LineOut") <= vendorPropertiesSize && sizeof("Streaming_LineOut") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_LineOut", sizeof("Streaming_LineOut"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; + if (DataPortNumber) + { + // UAJ Output uses DP 3 + *DataPortNumber = 3; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_HeadsetOutput") <= vendorPropertiesSize && sizeof("Streaming_HeadsetOutput") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_HeadsetOutput", sizeof("Streaming_HeadsetOutput"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; + if (DataPortNumber) + { + // UAJ Output uses DP 3 + *DataPortNumber = 3; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_Microphone") <= vendorPropertiesSize && sizeof("Streaming_Microphone") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_Microphone", sizeof("Streaming_Microphone"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + if (DataPortNumber) + { + // UAJ Input uses DP 2 + *DataPortNumber = 2; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_LineIn") <= vendorPropertiesSize && sizeof("Streaming_LineIn") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_LineIn", sizeof("Streaming_LineIn"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + if (DataPortNumber) + { + // UAJ Input uses DP 2 + *DataPortNumber = 2; + } + status = STATUS_SUCCESS; + } + else if (sizeof("Streaming_HeadsetMic") <= vendorPropertiesSize && sizeof("Streaming_HeadsetMic") == RtlCompareMemory((PBYTE)vendorPropertiesBuffer, "Streaming_HeadsetMic", sizeof("Streaming_HeadsetMic"))) + { + *CircuitId = DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + if (DataPortNumber) + { + // UAJ Input uses DP 2 + *DataPortNumber = 2; + } + status = STATUS_SUCCESS; + } + + // + // The below code would be replaced in a real DSP driver (or modified to use vendor-specific properties) + // + ULONG vendorAggCount = 0; + NTSTATUS aggCountStatus = Acpi->GetPropertyULong("acpi-vendor-mstest-aggregateddevice-count", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &vendorAggCount); + if (NT_SUCCESS(aggCountStatus) && vendorAggCount > 0 && vendorAggCount <= MaxPathDescriptors && PathDescriptors != nullptr) + { + // + // This endpoint supports aggregation. If we find the necessary properties for SDCA_PATH_DESCRIPTORS2 for each aggregated device + // we'll use the PathDescriptors for the endpoint. The PathDescriptors allows each aggregated device to use different channel masks. + // + const ULONG MAX_PROPERTY_SIZE = ARRAYSIZE("acpi-vendor-mstest-aggregateddevice-%d-dp-channel-mask"); + ULONG peripheralSuccessCount = 0; + size_t descriptorsSize = sizeof(*PathDescriptors) + sizeof(PathDescriptors->Descriptor[0]) * (vendorAggCount - 1); + + for (ULONG i = 0; i < vendorAggCount && i < MAX_AGGREGATED_DEVICES; ++i) + { + char propertyName[MAX_PROPERTY_SIZE]; + + PathDescriptors->Descriptor[i].Size = sizeof(PathDescriptors->Descriptor[1]); + PathDescriptors->Descriptor[i].Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + PathDescriptors->Descriptor[i].FunctionInformationId = i; + PathDescriptors->Descriptor[i].DataPortMap = SdcaDataPortMapIndexA; + PathDescriptors->Descriptor[i].DataPortConfig[0].Size = sizeof(SOUNDWIRE_DATAPORT_CONFIGURATION); + // EndpointId will be supplied during CreateStreamBridge + PathDescriptors->Descriptor[i].DataPortConfig[0].EndpointId = 0; + PathDescriptors->Descriptor[i].DataPortConfig[0].Modes = SoundWireDataPortModeIsochronous; + + // Values from the vendor blob of a partner's DSP driver + status = RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-aggregateddevice-%d-unique-id", i); + if (!NT_SUCCESS(status)) + { + break; + } + + // We need to be able to match each Descriptor we find with a specific aggregated device. The aggregated device ordering at runtime + // can be different, so we need to save the UniqueID for the audio function now. + // At pin connection, we will discover the aggregated devices and replace the Uniquie ID with the appropriate FunctionInformationId + status = Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &PathDescriptors->Descriptor[i].FunctionInformationId); + if (!NT_SUCCESS(status)) + { + break; + } + + status = RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-aggregateddevice-%d-terminal-id", i); + if (!NT_SUCCESS(status)) + { + break; + } + + status = Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &PathDescriptors->Descriptor[i].TerminalEntityId); + if (!NT_SUCCESS(status)) + { + break; + } + + status = RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-aggregateddevice-%d-dp-number", i); + if (!NT_SUCCESS(status)) + { + break; + } + + status = Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &PathDescriptors->Descriptor[i].DataPortConfig[0].DataPortNumber); + if (!NT_SUCCESS(status)) + { + break; + } + + status = RtlStringCbPrintfA(propertyName, sizeof(propertyName), "acpi-vendor-mstest-aggregateddevice-%d-dp-channel-mask", i); + if (!NT_SUCCESS(status)) + { + break; + } + + status = Acpi->GetPropertyULong(propertyName, ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &PathDescriptors->Descriptor[i].DataPortConfig[0].ChannelMask); + if (!NT_SUCCESS(status)) + { + break; + } + + ++peripheralSuccessCount; + } + + if (peripheralSuccessCount == vendorAggCount) + { + // Found all the data we wanted for each of the aggregated devices + PathDescriptors->Size = (ULONG)descriptorsSize; + PathDescriptors->Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + PathDescriptors->DescriptorCount = vendorAggCount; + PathDescriptors->SdcaPath = SdcaPathDefault; + } + + // Ignore failures retrieving optional properties + status = STATUS_SUCCESS; + } + + ULONG vendorDataPortNumber = ULONG_MAX; + ULONG vendorChannelMask = ULONG_MAX; + ULONG vendorTerminalId = ULONG_MAX; + + + // GetPropertyULong will leave the value as is (ULONG_MAX) if it isn't found + Acpi->GetPropertyULong("acpi-vendor-mstest-device-terminal-id", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &vendorTerminalId); + Acpi->GetPropertyULong("acpi-vendor-mstest-device-dp-number", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &vendorDataPortNumber); + Acpi->GetPropertyULong("acpi-vendor-mstest-device-dp-channel-mask", ACPI_METHOD_SECTION_DEVICE_PROPERTIES, vendorPropertiesBlock, &vendorChannelMask); + + // DataPortNumber by itself is retained to validate back compat with systems that don't support the + // new PathDescriptors2 structure + if (DataPortNumber) + { + // Example vendor property for a streaming device + if (vendorDataPortNumber != ULONG_MAX) + { + *DataPortNumber = vendorDataPortNumber; + } + } + + // Only fill out the PathDescriptors here if we didn't already fill it out with aggregated information + if (PathDescriptors && PathDescriptors->Size == 0) + { + // Example code if the vendor values have been discovered for a single non-aggregated endpoint + if ((vendorTerminalId != ULONG_MAX) && (vendorDataPortNumber != ULONG_MAX) && (vendorChannelMask != ULONG_MAX)) + { + // We have enough information to fill out the PathDescriptors structure + PathDescriptors->Size = sizeof(*PathDescriptors); + PathDescriptors->Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + PathDescriptors->SdcaPath = SdcaPathDefault; + // EndpointId will be filled in later + PathDescriptors->EndpointId = 0; + PathDescriptors->DescriptorCount = 1; + PathDescriptors->Descriptor[0].Size = sizeof(PathDescriptors->Descriptor[0]); + PathDescriptors->Descriptor[0].Version = SDCA_PATH_DESCRIPTOR2_VERSION_1; + PathDescriptors->Descriptor[0].FunctionInformationId = 0; + PathDescriptors->Descriptor[0].TerminalEntityId = vendorTerminalId; + // DataPortMap indicates which DPIndex entries are used, in this sample we'll only use + // a single data port and that will be DPIndex_A. + PathDescriptors->Descriptor[0].DataPortMap = SdcaDataPortMapIndexA; + PathDescriptors->Descriptor[0].DataPortConfig[0].Size = sizeof(PathDescriptors->Descriptor[0].DataPortConfig[0]); + PathDescriptors->Descriptor[0].DataPortConfig[0].DataPortNumber = vendorDataPortNumber; + // The Descriptor-specific EndpointId is ignored + PathDescriptors->Descriptor[0].DataPortConfig[0].EndpointId = 0; + // Mode may be specified as something other than Isochronous depending on hardware and configuration + PathDescriptors->Descriptor[0].DataPortConfig[0].Modes = SoundWireDataPortModeIsochronous; + PathDescriptors->Descriptor[0].DataPortConfig[0].ChannelMask = vendorChannelMask; + } + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtAcxFactoryCircuitCreateCircuitDevice( + _In_ WDFDEVICE Parent, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _Out_ WDFDEVICE * Device +) +{ + ACXOBJECTBAG circuitProperties; + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, CircuitId); + + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + *Device = NULL; + + // Create object bag from the CircuitProperties + ACX_OBJECTBAG_CONFIG propConfig; + ACX_OBJECTBAG_CONFIG_INIT(&propConfig); + propConfig.Handle = CircuitConfig->CircuitProperties; + propConfig.Flags |= AcxObjectBagConfigOpenWithHandle; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &propConfig, &circuitProperties)); + + auto cleanupPropConfig = scope_exit([=]() { + WdfObjectDelete(circuitProperties); + } + ); + + // Retrieve the intended Circuit ID from the object bag + GUID circuitId; + AcpiReader * acpiReader = GetAcpiReaderDeviceContext(Parent); + + RETURN_NTSTATUS_IF_TRUE(acpiReader == NULL, STATUS_INVALID_PARAMETER); + + RETURN_NTSTATUS_IF_FAILED(Dsp_DetermineCircuitDetailsFromVendorProperties(acpiReader, circuitProperties, &circuitId)); + + // Call the appropriate CreateCircuitDevice based on the Circuit ID + if (IsEqualGUID(circuitId, DSP_CIRCUIT_MICROPHONE_GUID) || IsEqualGUID(circuitId, DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID)) + { + status = DspC_EvtAcxFactoryCircuitCreateCircuitDevice(Parent, Factory, CircuitConfig, Device); + } + else if (IsEqualGUID(circuitId, DSP_CIRCUIT_SPEAKER_GUID) || IsEqualGUID(circuitId, DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID)) + { + status = DspR_EvtAcxFactoryCircuitCreateCircuitDevice(Parent, Factory, CircuitConfig, Device); + } + else + { + status = STATUS_NOT_SUPPORTED; + DrvLogError(g_SDCAVDspLog, FLAG_INIT, L"Unexpected CircuitId %!GUID!, %!STATUS!", &circuitId, status); + } + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + // + // On success, cache this device info. + // + if (NT_SUCCESS(status)) + { + status = Dsp_AddChildDeviceToCache(Factory, &CircuitConfig->CircuitUniqueId, *Device); + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVDspLog, FLAG_INIT, + L"Dsp_AddChildDeviceToCache(Factory=%p, ID=%!GUID!, WDFDEVICE=%p) failed, %!STATUS!", + Factory, &CircuitConfig->CircuitUniqueId, *Device, status); + + WdfObjectDelete(*Device); + *Device = NULL; + } + } +#endif + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_EvtAcxFactoryCircuitCreateCircuit( + _In_ WDFDEVICE Parent, + _In_ WDFDEVICE Device, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _In_ PACXCIRCUIT_INIT CircuitInit +) +{ + ACXOBJECTBAG circuitProperties; + + DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, CircuitId); + + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVDspLog); + + // Create object bag from the CompositeProperties + ACX_OBJECTBAG_CONFIG propConfig; + ACX_OBJECTBAG_CONFIG_INIT(&propConfig); + propConfig.Handle = CircuitConfig->CircuitProperties; + propConfig.Flags |= AcxObjectBagConfigOpenWithHandle; + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &propConfig, &circuitProperties)); + + auto cleanupPropConfig = scope_exit([=]() { + WdfObjectDelete(circuitProperties); + } + ); + + // Retrieve the intended Circuit ID from the object bag + GUID circuitId; + ULONG dataPortNumber = 0; + + PSDCA_PATH_DESCRIPTORS2 pathDescriptors = (PSDCA_PATH_DESCRIPTORS2)ExAllocatePool2( + POOL_FLAG_NON_PAGED, + sizeof(SDCA_PATH_DESCRIPTORS2) + sizeof(SDCA_PATH_DESCRIPTOR2)*(MAX_AGGREGATED_DEVICES-1), + DRIVER_TAG); + if (pathDescriptors == nullptr) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INSUFFICIENT_RESOURCES); + } + auto descriptors_free = scope_exit([&pathDescriptors]() + { + ExFreePool(pathDescriptors); + }); + + AcpiReader * acpiReader = GetAcpiReaderDeviceContext(Parent); + + RETURN_NTSTATUS_IF_TRUE(acpiReader == NULL, STATUS_INVALID_PARAMETER); + + RETURN_NTSTATUS_IF_FAILED(Dsp_DetermineCircuitDetailsFromVendorProperties( + acpiReader, + circuitProperties, + &circuitId, + &dataPortNumber, + MAX_AGGREGATED_DEVICES, + pathDescriptors)); + + AcxCircuitInitSetComponentId(CircuitInit, &circuitId); + + // Call the appropriate CreateCircuitDevice based on the Circuit ID + if (IsEqualGUID(circuitId, DSP_CIRCUIT_MICROPHONE_GUID) || IsEqualGUID(circuitId, DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID)) + { + return DspC_EvtAcxFactoryCircuitCreateCircuit(Parent, Device, Factory, CircuitConfig, CircuitInit, dataPortNumber, pathDescriptors); + } + else if (IsEqualGUID(circuitId, DSP_CIRCUIT_SPEAKER_GUID) || IsEqualGUID(circuitId, DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID)) + { + return DspR_EvtAcxFactoryCircuitCreateCircuit(Parent, Device, Factory, CircuitConfig, CircuitInit, dataPortNumber, pathDescriptors); + } + + status = STATUS_NOT_SUPPORTED; + DrvLogError(g_SDCAVDspLog, FLAG_INIT, L"Unexpected CircuitId %!GUID!, %!STATUS!", &circuitId, status); + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_AddFactoryCircuit( + _In_ WDFDEVICE Device +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + PDSP_DEVICE_CONTEXT devCtx = GetDspDeviceContext(Device); + PDSP_FACTORY_CONTEXT factoryCtx = NULL; + + ASSERT(devCtx != NULL); + + DECLARE_CONST_UNICODE_STRING(dspFactoryName, L"VirtualDspFactoryCircuit"); + DECLARE_CONST_UNICODE_STRING(dspFactoryUri, L"acpi:obj-path:\\_SB.PC00.HDAS"); + + // + // Get a FactoryCircuitInit structure. + // + PACXFACTORYCIRCUIT_INIT factoryInit = NULL; + factoryInit = AcxFactoryCircuitInitAllocate(Device); + + // + // Add factory identifiers. + // + RETURN_NTSTATUS_IF_FAILED(AcxFactoryCircuitInitAssignComponentUri(factoryInit, &dspFactoryUri)); + RETURN_NTSTATUS_IF_FAILED(AcxFactoryCircuitInitAssignName(factoryInit, &dspFactoryName)); + + // + // Add properties, events and methods. + // +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxFactoryCircuitInitAssignAcxRequestPreprocessCallback( + factoryInit, + Dsp_EvtFactoryRemoveCircuitRequestPreprocess, + (ACXCONTEXT)Device, + AcxRequestTypeMethod, + &KSMETHODSETID_AcxFactoryCircuit, + KSMETHOD_ACXFACTORYCIRCUIT_REMOVECIRCUIT)); +#endif + + // + // Assign the circuit's operation-callbacks. + // + ACX_FACTORY_CIRCUIT_OPERATION_CALLBACKS operationCallbacks; + ACX_FACTORY_CIRCUIT_OPERATION_CALLBACKS_INIT(&operationCallbacks); + operationCallbacks.EvtAcxFactoryCircuitCreateCircuitDevice = Dsp_EvtAcxFactoryCircuitCreateCircuitDevice; + operationCallbacks.EvtAcxFactoryCircuitCreateCircuit = Dsp_EvtAcxFactoryCircuitCreateCircuit; + AcxFactoryCircuitInitSetOperationCallbacks(factoryInit, &operationCallbacks); + + // + // Create the factory circuit. + // + WDF_OBJECT_ATTRIBUTES attributes; + ACXFACTORYCIRCUIT factory; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_FACTORY_CONTEXT); + attributes.ParentObject = Device; + attributes.EvtCleanupCallback = Dsp_EvtFactoryContextCleanup; + attributes.EvtDestroyCallback = Dsp_EvtFactoryContextDestroy; + + ASSERT(devCtx->Factory == NULL); + RETURN_NTSTATUS_IF_FAILED(AcxFactoryCircuitCreate(Device, &attributes, &factoryInit, &factory)); + ASSERT(factory != NULL); + + factoryCtx = GetDspFactoryContext(factory); + factoryCtx->Device = Device; + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + RETURN_NTSTATUS_IF_FAILED(Dsp_InitializeChildDevicesCache(factory)); +#endif // ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + + // + // Add circuit factory to device. + // It will remain added until the Device is cleaned up by WDF due to removal. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddFactoryCircuit(Device, factory)); + devCtx->Factory = factory; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_SendTestPropertyTo( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + if (Information) + { + *Information = 0; + } + + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(Circuit); + + ACXPIN pin; + if (circuitCtx->IsRenderCircuit) + { + pin = AcxCircuitGetPinById(Circuit, DspPinTypeBridge); + } + else + { + pin = AcxCircuitGetPinById(Circuit, DspCapturePinTypeBridge); + } + ASSERT(pin); + + DSP_PIN_CONTEXT* pinCtx = GetDspPinContext(pin); + ASSERT(pinCtx); + + RETURN_NTSTATUS_IF_TRUE(pinCtx->TargetCircuit == NULL, STATUS_INVALID_DEVICE_STATE); + + ACX_REQUEST_PARAMETERS requestParams; + ACX_REQUEST_PARAMETERS_INIT_PROPERTY( + &requestParams, + PropertySet, + PropertyId, + Verb, + AcxItemTypeCircuit, + 0, + Control, ControlCb, + Value, ValueCb + ); + + WDFREQUEST request; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Device; + RETURN_NTSTATUS_IF_FAILED(WdfRequestCreate(&attributes, AcxTargetCircuitGetWdfIoTarget(pinCtx->TargetCircuit), &request)); + auto request_free = scope_exit([&request]() + { + WdfObjectDelete(request); + }); + + RETURN_NTSTATUS_IF_FAILED(AcxTargetCircuitFormatRequestForProperty(pinCtx->TargetCircuit, request, &requestParams)); + + WDF_REQUEST_SEND_OPTIONS sendOptions; + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(5)); + + RETURN_NTSTATUS_IF_TRUE(!WdfRequestSend(request, AcxTargetCircuitGetWdfIoTarget(pinCtx->TargetCircuit), &sendOptions), STATUS_INVALID_DEVICE_REQUEST); + status = WdfRequestGetStatus(request); + if (Information) + { + *Information = WdfRequestGetInformation(request); + } + if (status == STATUS_BUFFER_OVERFLOW && ValueCb == 0) + { + // Don't trace this error, it's normal + return status; + } + RETURN_NTSTATUS_IF_FAILED(status); + + return status; +} + +PAGED_CODE_SEG +VOID +Dsp_SendVendorSpecificProperties( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ BOOLEAN SetValue +) +{ + VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL control = { 0 }; + VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA data = { 0 }; + ULONG_PTR info; + + PAGED_CODE(); + + control.VendorSpecificId = VirtualStackVendorSpecificRequestGetTestData; + control.VendorSpecificSize = sizeof(control); + control.Data.DataPort = 0; + control.Data.EndpointId = 0; + + NTSTATUS status = Dsp_SendTestPropertyTo( + Device, + Circuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_VENDOR_SPECIFIC, + AcxPropertyVerbGet, + &control, + sizeof(control), + nullptr, + 0, + &info); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"KSPROPERTY_SDCA_VENDOR_SPECIFIC GetTestData for size request returns %!STATUS! (%p)", status, (void*)info); + + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_VENDOR_SPECIFIC, + AcxPropertyVerbGet, + &control, + sizeof(control), + &data, + sizeof(data), + &info); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"KSPROPERTY_SDCA_VENDOR_SPECIFIC GetTestData returns %#x : %#x, %!STATUS!", data.Test1, data.Test2, status); + + RtlZeroMemory(&control, sizeof(control)); + control.VendorSpecificId = VirtualStackVendorSpecificRequestSetTestConfig; + control.VendorSpecificSize = sizeof(control); + control.Config.IsScatterGather = SetValue; + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_VENDOR_SPECIFIC, + AcxPropertyVerbSet, + &control, + sizeof(control), + &data, + sizeof(data), + &info); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"KSPROPERTY_SDCA_VENDOR_SPECIFIC SetTestParam returned %!STATUS!", status); +} + +PAGED_CODE_SEG +VOID +Dsp_EvtFactoryContextCleanup( + _In_ WDFOBJECT Factory + ) +{ + PAGED_CODE(); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + Dsp_CleanupChildDevicesCache((ACXFACTORYCIRCUIT)Factory); +#else + UNREFERENCED_PARAMETER(Factory); +#endif +} + +PAGED_CODE_SEG +VOID +Dsp_EvtFactoryContextDestroy( + _In_ WDFOBJECT Factory + ) +{ + PAGED_CODE(); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + Dsp_DeleteChildDevicesCache((ACXFACTORYCIRCUIT)Factory); +#else + UNREFERENCED_PARAMETER(Factory); +#endif +} + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 +PAGED_CODE_SEG +NTSTATUS +Dsp_InitializeChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &factoryCtx->CacheLock)); + RETURN_NTSTATUS_IF_FAILED(WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &factoryCtx->Cache)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +VOID +Dsp_CleanupChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + WDFOBJECT child = NULL; + + PAGED_CODE(); + + // + // Factory is going away, cleanup child devices cache. + // + if (factoryCtx->Cache == NULL || factoryCtx->CacheLock == NULL) + { + return; // Nothing to do. + } + + WdfWaitLockAcquire(factoryCtx->CacheLock, NULL); + + while ((child = WdfCollectionGetFirstItem(factoryCtx->Cache)) != NULL) + { + PDSP_DEVICEID_CONTEXT idCtx = GetDspDeviceIdContext(child); + + // + // - zero out ID. + // - remove the item from the cache. + // + idCtx->UniqueID = NULL_GUID; + WdfCollectionRemoveItem(factoryCtx->Cache, 0); + } + + WdfWaitLockRelease(factoryCtx->CacheLock); +} + +PAGED_CODE_SEG +VOID +Dsp_DeleteChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + + PAGED_CODE(); + + if (factoryCtx->Cache != NULL) + { + WdfObjectDelete(factoryCtx->Cache); + factoryCtx->Cache = NULL; + } + + if (factoryCtx->CacheLock != NULL) + { + WdfObjectDelete(factoryCtx->CacheLock); + factoryCtx->CacheLock = NULL; + } +} + +PAGED_CODE_SEG +bool +Dsp_IsChildDeviceInCacheLocked( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + ULONG count = WdfCollectionGetCount(factoryCtx->Cache); + bool isPresent = false; + + PAGED_CODE(); + + for (ULONG i = 0; i < count; i++) + { + WDFDEVICE child = NULL; + PDSP_DEVICEID_CONTEXT idCtx = NULL; + + child = (WDFDEVICE)WdfCollectionGetItem(factoryCtx->Cache, i); + idCtx = GetDspDeviceIdContext(child); + + if ((idCtx != 0) && IsEqualGUID(idCtx->UniqueID, *UniqueId)) + { + // Found it. + isPresent = true; + break; + } + } + + return isPresent; +} + +PAGED_CODE_SEG +NTSTATUS +Dsp_AddChildDeviceToCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId, + _In_ WDFDEVICE Device + ) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + + PAGED_CODE(); + + WdfWaitLockAcquire(factoryCtx->CacheLock, NULL); + + // + // Make sure there is not another device with the same ID. + // + if (Dsp_IsChildDeviceInCacheLocked(Factory, UniqueId)) + { + status = STATUS_DEVICE_ALREADY_ATTACHED; + } + else + { + // + // Attach a device ID context if not already present. + // + PDSP_DEVICEID_CONTEXT idCtx = GetDspDeviceIdContext(Device); + if (idCtx == NULL) + { + // Add the device ID context. + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_DEVICEID_CONTEXT); + attributes.EvtCleanupCallback = Dsp_EvtDeviceIdContextCleanup; + + status = WdfObjectAllocateContext(Device, &attributes, (PVOID*)&idCtx); + if (!NT_SUCCESS(status)) + { + idCtx = NULL; // just in case. + DrvLogError(g_SDCAVDspLog, FLAG_INIT, + "Failed to allocate a DSP_DEVICEID_CONTEXT on WDFDEVICE %p, %!STATUS!", + Device, status); + } + } + else + { + // This should not happen, but just in case, cleanup the context. + ASSERT(FALSE); + idCtx->UniqueID = NULL_GUID; + if (idCtx->Factory != NULL) + { + WdfObjectDereferenceWithTag(idCtx->Factory, (PVOID)DRIVER_TAG); + idCtx->Factory = NULL; + } + } + + if (idCtx != NULL) + { + // + // Store the unique ID of this device. + // + idCtx->UniqueID = *UniqueId; + + // + // Take a strong ref on the factory object. + // Ref is removed on context cleanup. + // + idCtx->Factory = Factory; + WdfObjectReferenceWithTag(Factory, (PVOID)DRIVER_TAG); + + // + // Add the device to our cache. + // + status = WdfCollectionAdd(factoryCtx->Cache, Device); + } + } + + WdfWaitLockRelease(factoryCtx->CacheLock); + + return status; +} + +PAGED_CODE_SEG +WDFDEVICE +Dsp_RemoveChildDeviceFromCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + WDFDEVICE child = NULL; + ULONG count; + + PAGED_CODE(); + + WdfWaitLockAcquire(factoryCtx->CacheLock, NULL); + + count = WdfCollectionGetCount(factoryCtx->Cache); + + for (ULONG i = 0; i < count; i++) + { + PDSP_DEVICEID_CONTEXT idCtx = NULL; + WDFDEVICE device = NULL; + + device = (WDFDEVICE)WdfCollectionGetItem(factoryCtx->Cache, i); + idCtx = GetDspDeviceIdContext(device); + + if ((idCtx != 0) && IsEqualGUID(idCtx->UniqueID, *UniqueId)) + { + // Found it. + // - zero out ID. + // - add a ref for the caller. + // - remove the item from the cache. + idCtx->UniqueID = NULL_GUID; + WdfObjectReferenceWithTag(device, (PVOID)DRIVER_TAG); + WdfCollectionRemoveItem(factoryCtx->Cache, i); + child = device; + break; + } + } + + WdfWaitLockRelease(factoryCtx->CacheLock); + + return child; +} + +PAGED_CODE_SEG +VOID +Dsp_PurgeChildDeviceFromCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ WDFDEVICE Device + ) +{ + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(Factory); + PDSP_DEVICEID_CONTEXT idCtx = GetDspDeviceIdContext(Device); + WDFDEVICE child = NULL; + + PAGED_CODE(); + + WdfWaitLockAcquire(factoryCtx->CacheLock, NULL); + + // + // Scan the cache only if the device's unique-id is not null. + // + if (idCtx != NULL && !IsEqualGUID(NULL_GUID, idCtx->UniqueID)) + { + ULONG count = WdfCollectionGetCount(factoryCtx->Cache); + + for (ULONG i = 0; i < count; i++) + { + child = (WDFDEVICE)WdfCollectionGetItem(factoryCtx->Cache, i); + if (child == Device) + { + // + // Found it. + // - zero out ID. + // - remove the item from the cache. + // + idCtx->UniqueID = NULL_GUID; + WdfCollectionRemoveItem(factoryCtx->Cache, i); + break; + } + } + } + + WdfWaitLockRelease(factoryCtx->CacheLock); +} + +PAGED_CODE_SEG +VOID +Dsp_EvtDeviceIdContextCleanup( + _In_ WDFOBJECT Device + ) +{ + PDSP_DEVICEID_CONTEXT idCtx = GetDspDeviceIdContext(Device); + + PAGED_CODE(); + + Dsp_PurgeChildDeviceFromCache(idCtx->Factory, (WDFDEVICE)Device); + WdfObjectDereferenceWithTag(idCtx->Factory, (PVOID)DRIVER_TAG); +} + +PAGED_CODE_SEG +VOID +Dsp_EvtFactoryCircuitRemoveCircuitCallback +( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + NTSTATUS status = STATUS_NOT_SUPPORTED; + ACXFACTORYCIRCUIT factory = (ACXFACTORYCIRCUIT)Object; + PDSP_FACTORY_CONTEXT factoryCtx = GetDspFactoryContext(factory); + WDFDEVICE child = NULL; + PACX_FACTORY_CIRCUIT_REMOVE_CIRCUIT args; + ULONG argsCb = sizeof(ACX_FACTORY_CIRCUIT_REMOVE_CIRCUIT); + ACX_REQUEST_PARAMETERS params; + + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + ASSERT(params.Type == AcxRequestTypeMethod); + ASSERT(params.Parameters.Method.Verb == AcxMethodVerbSend); + ASSERT(params.Parameters.Method.ArgsCb >= argsCb); + + args = (PACX_FACTORY_CIRCUIT_REMOVE_CIRCUIT)params.Parameters.Method.Args; + argsCb = params.Parameters.Method.ArgsCb; // use real value. + + if (args->Size < argsCb) + { + status = STATUS_INVALID_PARAMETER; + DrvLogError(g_SDCAVDspLog, FLAG_GENERIC, + "ACX_FACTORY_CIRCUIT_REMOVE_CIRCUIT.Size %d is invalid, it should be >= %d, %!STATUS!", + args->Size, argsCb, status); + goto exit; + } + + // + // Remove the circut/circuit-device. + // If found, there is a pending WDF ref on the object. + // + child = Dsp_RemoveChildDeviceFromCache(factory, &args->CircuitUniqueId); + if (child == NULL) + { + // Device is gone. Nothing to do. + status = STATUS_SUCCESS; + goto exit; + } + + // + // Tell ACX not to enum this child device anymore. + // + status = AcxDeviceRemoveCircuitDevice(factoryCtx->Device, child); + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVDspLog, FLAG_GENERIC, + "Parent %p, ACXFACTORYCIRCUIT %p, Child %p, AcxDeviceRemoveCircuitDevice failed, %!STATUS!", + factoryCtx->Device, factory, child, status); + goto exit; + } + + status = STATUS_SUCCESS; + +exit: + if (child != NULL) + { + WdfObjectDereferenceWithTag(child, (PVOID)DRIVER_TAG); + } + + WdfRequestComplete(Request, status); +} + +PAGED_CODE_SEG +VOID +Dsp_EvtFactoryRemoveCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + ASSERT(Object); + ASSERT(Request); + + Dsp_EvtFactoryCircuitRemoveCircuitCallback(Object, Request); +} +#endif //ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/driver.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/driver.cpp new file mode 100644 index 00000000..98cc6d73 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/driver.cpp @@ -0,0 +1,172 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Driver.cpp + +Abstract: + + Sample Soundwire DSP Driver. + +Environment: + + Kernel mode only + +--*/ + +#include "private.h" +#include "trace.h" + +#ifndef __INTELLISENSE__ +#include "driver.tmh" +#endif + +RECORDER_LOG g_SDCAVDspLog{ nullptr }; + +PAGED_CODE_SEG +void Dsp_DriverUnload (_In_ WDFDRIVER Driver) +{ + PAGED_CODE(); + + if (!Driver) + { + return; + } + + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); + + return; +} + +INIT_CODE_SEG +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WPP_INIT_TRACING(DriverObject, RegistryPath); + + auto exit = scope_exit([&status, &DriverObject]() { + if (!NT_SUCCESS(status)) + { + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + WPP_CLEANUP(DriverObject); + } + else + { + DrvLogInfo(g_SDCAVDspLog, FLAG_INIT, "ACX SDCA Virtual DSP Driver Init complete, %!STATUS!", status); + } + }); + + RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath)); + + // + // Initiialize 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, + // you can override that by manually setting the EvtDriverUnload in the + // config structure. In general xxx_CONFIG_INIT macros are provided to + // initialize most commonly used members. + // + + WDF_DRIVER_CONFIG wdfCfg; + WDF_DRIVER_CONFIG_INIT(&wdfCfg, Dsp_EvtBusDeviceAdd); + wdfCfg.EvtDriverUnload = Dsp_DriverUnload; + + // + // Add a driver context. (for illustration purposes only). + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_DRIVER_CONTEXT); + + // + // Create a framework driver object to represent our driver. + // + WDFDRIVER driver; + RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, // Driver Attributes + &wdfCfg, // Driver Config Info + &driver // hDriver + )); + + RECORDER_CONFIGURE_PARAMS recorderConfig; + RECORDER_CONFIGURE_PARAMS_INIT(&recorderConfig); + recorderConfig.CreateDefaultLog = FALSE; + WppRecorderConfigure(&recorderConfig); + + RECORDER_LOG_CREATE_PARAMS recorderLogCreateParams; + RECORDER_LOG_CREATE_PARAMS_INIT(&recorderLogCreateParams, NULL); + recorderLogCreateParams.TotalBufferSize = WPP_TOTAL_BUFFER_SIZE; + recorderLogCreateParams.ErrorPartitionSize = WPP_ERROR_PARTITION_SIZE; + + RtlStringCbPrintfA(recorderLogCreateParams.LogIdentifier, + RECORDER_LOG_IDENTIFIER_MAX_CHARS, + "SDCAVDsp"); + + RECORDER_LOG logHandle = NULL; + status = WppRecorderLogCreate(&recorderLogCreateParams, &logHandle); + if (!NT_SUCCESS(status)) + { + logHandle = NULL; + + // Non fatal failure + status = STATUS_SUCCESS; + } + + g_SDCAVDspLog = logHandle; + + // + // Post init. + // + ACX_DRIVER_CONFIG acxCfg; + ACX_DRIVER_CONFIG_INIT(&acxCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg)); + + return status; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.cpp new file mode 100644 index 00000000..c86af13a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.cpp @@ -0,0 +1,606 @@ +/*++ + + 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: + + offloadStreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls offload streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "offloadStreamEngine.h" + +#ifndef __INTELLISENSE__ +#include "offloadStreamEngine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +COffloadStreamEngine::COffloadStreamEngine( + ACXSTREAM Stream, + ACXDATAFORMAT StreamFormat, + CSimPeakMeter *circuitPeakmeter +) :CStreamEngine(Stream, StreamFormat, circuitPeakmeter) +{ + PAGED_CODE(); + + m_BufferReadTimer = NULL; + m_LastBufferTimer = NULL; + m_PacketsWritten = 0; + m_PacketsRead = 0; + m_SinglePacketPosition = 0; +} + +_Use_decl_annotations_ +#pragma code_seg() +COffloadStreamEngine::~COffloadStreamEngine() +{ +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + // CStreamEngine::PrepareHardware will update state to Pause, but we don't + // want to be in Pause state if any of the below actions fail. + m_CurrentState = AcxStreamStateStop; + + // + // Buffer read callbacks + // + WDF_TIMER_CONFIG timerConfig; + LONG period = (LONG)((ULONGLONG)m_PacketSize * HNS_PER_SEC / (ULONGLONG)GetBytesPerSecond()); + WDF_TIMER_CONFIG_INIT_PERIODIC( + &timerConfig, + COffloadStreamEngine::s_EvtBufferReadTimerCallback, + period / HNSTIME_PER_MILLISECOND + ); + timerConfig.UseHighResolutionTimer = WdfTrue; + + WDF_OBJECT_ATTRIBUTES timerAttributes; + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes, STREAM_TIMER_CONTEXT); + timerAttributes.ParentObject = m_Stream; + + RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate( + &timerConfig, + &timerAttributes, + &m_BufferReadTimer + )); + + auto bt_free = scope_exit([this]() { + WdfObjectDelete(m_BufferReadTimer); + m_BufferReadTimer = NULL; + }); + + PSTREAM_TIMER_CONTEXT timerCtx; + timerCtx = GetStreamTimerContext(m_BufferReadTimer); + timerCtx->StreamEngine = this; + + // + // Last Buffer read callback + // + WDF_TIMER_CONFIG_INIT( + &timerConfig, + COffloadStreamEngine::s_EvtLastBufferTimerCallback + ); + timerConfig.UseHighResolutionTimer = WdfTrue; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes, STREAM_TIMER_CONTEXT); + timerAttributes.ParentObject = m_Stream; + + RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate( + &timerConfig, + &timerAttributes, + &m_LastBufferTimer + )); + + auto lbt_free = scope_exit([this]() { + WdfObjectDelete(m_LastBufferTimer); + m_LastBufferTimer = NULL; + }); + + timerCtx = GetStreamTimerContext(m_LastBufferTimer); + timerCtx->StreamEngine = this; + + RETURN_NTSTATUS_IF_FAILED(m_SaveData.SetDataFormat((PKSDATAFORMAT)AcxDataFormatGetKsDataFormat(m_StreamFormat))); + + RETURN_NTSTATUS_IF_FAILED(m_SaveData.Initialize(TRUE)); + + RETURN_NTSTATUS_IF_FAILED(m_SaveData.SetMaxWriteSize(m_PacketSize * m_PacketsCount * MAX_FILE_WRITE_FRAMES)); + + m_CurrentState = AcxStreamStatePause; + + bt_free.release(); + lbt_free.release(); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_SaveData.WaitAllWorkItems(); + m_SaveData.Cleanup(); + + if (m_BufferReadTimer) + { + WdfTimerStop(m_BufferReadTimer, TRUE); + WdfObjectDelete(m_BufferReadTimer); + m_BufferReadTimer = NULL; + } + + if (m_LastBufferTimer) + { + WdfTimerStop(m_LastBufferTimer, TRUE); + WdfObjectDelete(m_LastBufferTimer); + m_LastBufferTimer = NULL; + } + + m_LinearBufferClock.Stop(); + + m_PacketsWritten = 0; + m_PacketsRead = 0; + + CStreamEngine::ReleaseHardware(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::Run() +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::Run"); + + if (m_CurrentState != AcxStreamStatePause) + { + status = STATUS_INVALID_STATE_TRANSITION; + return status; + } + + ULONGLONG bytesPerSec = GetBytesPerSecond(); + + ULONGLONG elapsedTimeWhenPaused = m_LinearBufferClock.GetElapsedTime(NULL); + if (elapsedTimeWhenPaused) + { + // Stream has resumed from pause + // Calculate remaining buffer for next notification + + // Remaining buffer from when stream was paused + // Hardware might have cycled more than the bytes written + // This can happen if there was a glitch and hardware was + // starved + ULONGLONG packetTime = (ULONGLONG)m_PacketSize * HNS_PER_SEC / bytesPerSec; + LONG remainingTime = (LONG)((ULONGLONG)elapsedTimeWhenPaused % packetTime); + WdfTimerStart(m_BufferReadTimer, WDF_REL_TIMEOUT_IN_MS(remainingTime / HNSTIME_PER_MILLISECOND)); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::Run - Notification Timer Started - first timeout :%d ms", (ULONG)(remainingTime / HNSTIME_PER_MILLISECOND)); + } + else + { + // Run has been called first time on this stream + LONG period = (LONG)((ULONGLONG)m_PacketSize * HNS_PER_SEC / (ULONGLONG)bytesPerSec); + WdfTimerStart(m_BufferReadTimer, WDF_REL_TIMEOUT_IN_MS(period / HNSTIME_PER_MILLISECOND)); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::Run - Notification Timer Started - first timeout :%d ms", (ULONG)(period / HNSTIME_PER_MILLISECOND)); + } + + m_LinearBufferClock.Run(); + m_CurrentState = AcxStreamStateRun; + + m_PeakMeter.StartStream(); + m_pCircuitPeakmeter->StartStream(); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::Pause() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::Pause - from %d", m_CurrentState); + + RETURN_NTSTATUS_IF_TRUE(m_CurrentState != AcxStreamStateRun, STATUS_INVALID_STATE_TRANSITION); + + WdfTimerStop(m_BufferReadTimer, TRUE); + + m_LinearBufferClock.Pause(); + + m_PeakMeter.StopStream(); + m_pCircuitPeakmeter->StopStream(); + + m_CurrentState = AcxStreamStatePause; + + return status; +} + +_Use_decl_annotations_ +#pragma code_seg() +NTSTATUS +COffloadStreamEngine::GetPresentationPosition( + PULONGLONG PositionInBlocks, + PULONGLONG QPCPosition +) +{ + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::GetPresentationPosition"); + + ULONG blockAlign; + LARGE_INTEGER qpc; + + blockAlign = AcxDataFormatGetBlockAlign(m_StreamFormat); + qpc = KeQueryPerformanceCounter(NULL); + + ULONGLONG streamPosition = m_LinearBufferClock.GetElapsedTime(NULL); + + // Simulate Presentation position lag by 20 ms + if (streamPosition > (OFFLOAD_PRESENTATION_POSITION_LAG_IN_MS * HNSTIME_PER_MILLISECOND)) + { + streamPosition -= (OFFLOAD_PRESENTATION_POSITION_LAG_IN_MS * HNSTIME_PER_MILLISECOND); + } + else + { + streamPosition = 0; + } + + *PositionInBlocks = (streamPosition * GetBytesPerSecond() / HNS_PER_SEC) / blockAlign; + + *QPCPosition = (ULONGLONG)qpc.QuadPart; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +#pragma code_seg() +NTSTATUS +COffloadStreamEngine::GetLinearBufferPosition( + PULONGLONG Position +) +{ + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::GetLinearBufferPosition"); + + ULONGLONG bytesPerSecond = GetBytesPerSecond(); + ULONGLONG currentTime = m_LinearBufferClock.GetElapsedTime(NULL); + + // Update position + *Position = currentTime * bytesPerSecond / HNS_PER_SEC; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::SetCurrentWritePosition( + ULONG Position +) +{ + PAGED_CODE(); + + if (m_PacketsCount == 1) + { + return SetCurrentWritePositionSinglePacket(Position); + } + + // Determine buffer + // Designed for ping-pong + // Position == m_PacketSize, ping buffer was just filled + // Position == m_PacketSize * 2, pong buffer was just filled + ULONG packetIndex = Position == m_PacketSize ? 0 : 1; + + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::SetCurrentWritePosition, Position = 0x%08x, PacketIndex :%d", Position, packetIndex); + + // + // Detect if the packet just written is incorrect + // + ULONG packetsRead = (ULONG)InterlockedCompareExchange((LONG *)&m_PacketsRead, -1, -1); + + if (m_CurrentState == AcxStreamStateRun) + { + ULONG expectedPacketIndex = (packetsRead % 2) ? 0 : 1; + if (packetIndex != expectedPacketIndex) + { + DrvLogError(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine incorrect packet write: %d, Packets Read: %08d", packetIndex, packetsRead); + // \TODO: ACX doesn't recover from this error + // Continuing automatically recovers with next call + //return STATUS_DATA_OVERRUN; + } + } + + // + // Catch up to packets read + 1 + // This is to recover from condition when OS was not writing enough data + // + (ULONG)InterlockedExchange((LONG *)&m_PacketsWritten, packetsRead + 1); + + PBYTE packetBuffer = NULL; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + m_SaveData.WriteData(packetBuffer, m_PacketSize); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::SetCurrentWritePositionSinglePacket( + ULONG Position +) +{ + PAGED_CODE(); + + // Offload streams are almost always 2-packet. However, it is possible to create an offload stream + // as a timer-driven (single packet) stream. This code will ensure correct behavior in this case. + ULONG packetIndex = 0; + + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::SetCurrentWritePositionSinglePacket, Position = 0x%08x, PacketIndex :%d", Position, packetIndex); + + // + // Detect if the packet just written is incorrect + // + ULONG packetsRead = (ULONG)InterlockedCompareExchange((LONG *)&m_PacketsRead, -1, -1); + + // Position has wrapped, can increment the written count. + if (Position < m_SinglePacketPosition) + { + // + // Catch up to packets read + 1 + // This is to recover from condition when OS was not writing enough data + // + (ULONG)InterlockedExchange((LONG*)&m_PacketsWritten, packetsRead + 1); + } + + PBYTE packetBuffer = NULL; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + // For single-packet the offset should be 0. + packetBuffer += m_FirstPacketOffset; + + // AudioKSE adds 1 to the position + Position -= 1; + Position %= m_PacketSize; + + if (Position <= m_SinglePacketPosition) + { + // Handle the case of wraparound by copying from the last position to the end of the buffer + m_SaveData.WriteData(packetBuffer + m_SinglePacketPosition, m_PacketSize - m_SinglePacketPosition); + m_SinglePacketPosition = 0; + } + // Write from the last position (0 in the case of wraparound) to the new Position + m_SaveData.WriteData(packetBuffer + m_SinglePacketPosition, Position); + m_SinglePacketPosition = Position; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::SetLastBufferPosition( + ULONG Position +) +{ + PAGED_CODE(); + + ULONG bytesPerSec = GetBytesPerSecond(); + + // Determine buffer + ULONG packetIndex = Position < m_PacketSize ? 0 : 1; + ULONG lastBufferSize = Position <= m_PacketSize ? Position : Position - m_PacketSize; + + // time for rendering last buffer + ULONGLONG lastBufferTime = (ULONGLONG)lastBufferSize * HNS_PER_SEC / (ULONGLONG)bytesPerSec; + + ULONGLONG totalStreamTime = (ULONGLONG)m_PacketsWritten* (ULONGLONG)m_PacketSize* HNS_PER_SEC / (ULONGLONG)bytesPerSec; + totalStreamTime += (ULONGLONG)lastBufferTime; + + // Simulate Presentation position lag by 20 ms + ULONGLONG presentationTime = m_LinearBufferClock.GetElapsedTime(NULL) - (OFFLOAD_PRESENTATION_POSITION_LAG_IN_MS * HNSTIME_PER_MILLISECOND); + + lastBufferTime = totalStreamTime - presentationTime; + + // + // Start last buffer timer + // + RETURN_NTSTATUS_IF_TRUE_MSG(NULL == m_LastBufferTimer, STATUS_INVALID_PARAMETER, L"Set Last Buffer Position called out of sequence - without calling prepare hardware"); + WdfTimerStart(m_LastBufferTimer, WDF_REL_TIMEOUT_IN_MS(lastBufferTime / HNSTIME_PER_MILLISECOND)); + + PBYTE packetBuffer = NULL; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + m_SaveData.WriteData(packetBuffer, lastBufferSize); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +COffloadStreamEngine::AssignDrmContentId( + ULONG, + PACXDRMRIGHTS DrmRights +) +{ + PAGED_CODE(); + + // + // 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. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // Loopback: if CopyProtect is true, disable loopback stream. + // + + // + // 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 AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +COffloadStreamEngine::s_EvtBufferReadTimerCallback( + WDFTIMER Timer +) +{ + COffloadStreamEngine * This; + PSTREAM_TIMER_CONTEXT timerCtx; + + // Get our stream engine pointer from the timer context + timerCtx = GetStreamTimerContext(Timer); + This = (COffloadStreamEngine *)timerCtx->StreamEngine; + + // Call the BufferReadCallback for the engine + This->BufferReadCallback(); +} + +// Callback indicating buffer read complete +_Use_decl_annotations_ +#pragma code_seg() +VOID +COffloadStreamEngine::BufferReadCallback() +{ + // Save the time at which we moved to the next packet + ULONGLONG qpcCompleted; + qpcCompleted = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart; + + ULONG packetsWritten = (ULONG)InterlockedCompareExchange((LONG*)&m_PacketsWritten, -1, -1); + + // We've completed a packet! Increment our currently active packet + ULONG packetsRead = (ULONG)InterlockedIncrement((LONG *)&m_PacketsRead) - 1; + + // + // \TODO + // Detect if hardware has cycled more than the OS. + // Can happen if application doesn't write data on time + // + if(packetsRead > packetsWritten) + { + DrvLogError(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine starved PacketsWritten: %08d, Packets Read: %08d", packetsWritten, packetsRead); + } + + // Tell ACX we've completed the packet. + // 0 based packet count + (void)AcxRtStreamNotifyPacketComplete(m_Stream, (ULONGLONG)packetsRead, qpcCompleted); + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::BufferReadCallback packet complete - %d", packetsRead); +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +COffloadStreamEngine::s_EvtLastBufferTimerCallback( + WDFTIMER Timer +) +{ + COffloadStreamEngine * This; + PSTREAM_TIMER_CONTEXT timerCtx; + + // Get our stream engine pointer from the timer context + timerCtx = GetStreamTimerContext(Timer); + This = (COffloadStreamEngine *)timerCtx->StreamEngine; + + // Call the LastBufferRenderComplete for the engine + This->LastBufferRenderComplete(); +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +COffloadStreamEngine::LastBufferRenderComplete() +{ + // Save the time at which we moved to the next packet + ULONGLONG qpcCompleted; + qpcCompleted = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart; + + ULONGLONG completedPacket; + completedPacket = (ULONG)InterlockedIncrement((LONG*)&m_PacketsRead) - 1; + + // Tell ACX we've completed the packet. + (void)AcxRtStreamNotifyPacketComplete(m_Stream, completedPacket, qpcCompleted); + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"COffloadStreamEngine::LastBufferRenderComplete packet complete - %d", (ULONG)completedPacket); +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +COffloadStreamEngine::ProcessPacket() +{ +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.h new file mode 100644 index 00000000..4c325dda --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/offloadStreamEngine.h @@ -0,0 +1,172 @@ +/*++ + + 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: + + offloadStreamEngine.h + +Abstract: + + Virtual Streaming Engine - this module controls offload streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +#include "streamengine.h" +#include "PositionSimClock.h" + +#define MAX_FILE_WRITE_FRAMES (16) +#define OFFLOAD_PRESENTATION_POSITION_LAG_IN_MS (20) + +class COffloadStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + COffloadStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CSimPeakMeter *circuitPeakmeter + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + ~COffloadStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + NTSTATUS + GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + NTSTATUS + GetLinearBufferPosition( + _Out_ PULONGLONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetCurrentWritePosition( + _In_ ULONG Position + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetLastBufferPosition( + _In_ ULONG Position + ); + +protected: + WDFTIMER m_BufferReadTimer; + WDFTIMER m_LastBufferTimer; + + CPositionSimClock m_LinearBufferClock; + + CSaveData m_SaveData; + + // Number of packets written by OS + ULONG m_PacketsWritten; + + // Number of packets read by hardware + ULONG m_PacketsRead; + + ULONG m_SinglePacketPosition; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ProcessPacket(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetCurrentWritePositionSinglePacket( + _In_ ULONG Position + ); + + static + __drv_maxIRQL(DISPATCH_LEVEL) + _Function_class_(EVT_WDF_TIMER) + #pragma code_seg() + VOID s_EvtBufferReadTimerCallback( + _In_ WDFTIMER Timer + ); + + static + __drv_maxIRQL(DISPATCH_LEVEL) + _Function_class_(EVT_WDF_TIMER) + #pragma code_seg() + VOID s_EvtLastBufferTimerCallback( + _In_ WDFTIMER Timer + ); + + // Callback indicating buffer read complete + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + BufferReadCallback(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + LastBufferRenderComplete(); +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/private.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/private.h new file mode 100644 index 00000000..065b3375 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/private.h @@ -0,0 +1,803 @@ +/*++ + +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: + + private.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +Notes: + + Workarounds: + + ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + enables the logic to workaround an ACX v1.0 issue related to ACXFACTORYCIRCUIT race with Add/Remove child WDFDEVICE. + this issue has been fixed in ACX v1.1. + + ACX_WORKAROUND_ACXPIN_01 + enables the logic to workaround an ACX v1.0 issue related to ACXPIN's KSPROPERTY_PIN_CINSTANCES to return the pin's + stream instances vs. returning the total # of streams on a circuit. This # is not the same when circuit supports an + audio engine node, and client has instantiated streams on several pins (host/loopback/offload). + this issue has been fixed in ACX v1.1. + + ACX_WORKAROUND_ACXPIN_02 + enables the logic to workaround an ACX v1.1 issue related to ACXPIN's KSPROPERTY_PIN_PROPOSEDATAFORMAT set requests + directed to an 'offload' pin of an audio engine. The workaround fails the request if there are no enough resources + (streams). ACX will be enhanced in the future to automatically check this when the pin is tagged as 'offload' pin. + ACX_WORKAROUND_ACXPIN_01 must be enabled as well for ACX_WORKAROUND_ACXPIN_02 to work. + +--*/ + +#ifndef _PRIVATE_H_ +#define _PRIVATE_H_ + +#include "cpp_utils.h" + +#include "stdunk.h" +#include <mmsystem.h> +#include <ks.h> +#include <ksmedia.h> + +#include "NewDelete.h" + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#pragma warning(disable:4200) // +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int + +#include <initguid.h> +#include <ntddk.h> +#include <ntstrsafe.h> +#include <ntintsafe.h> +#include <TestProperties.h> + +#pragma warning(default:4200) +#pragma warning(default:4201) +#pragma warning(default:4214) + +#include <wdf.h> +#include <acx.h> + +#include "AudioAggregation.h" +#include "soundwirecontroller.h" +#include "sdcastreaming.h" + +#include "trace.h" + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +extern RECORDER_LOG g_SDCAVDspLog; + +// Check for workaround dependencies. +#ifdef ACX_WORKAROUND_ACXPIN_02 + #ifndef ACX_WORKAROUND_ACXPIN_01 + #error ACX_WORKAROUND_ACXPIN_02 requires ACX_WORKAROUND_ACXPIN_01. + #endif +#endif + +// Copied from cfgmgr32.h +#if !defined(MAX_DEVICE_ID_LEN) +#define MAX_DEVICE_ID_LEN 200 +#endif + +// Define a NULL GUID if not already defined. +#if !defined(NULL_GUID) +#define NULL_GUID { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } +#endif + +// SDCA Sample driver + +#define DRIVER_TAG (ULONG) 'Dcds' + +// Number of millisecs per sec. +#define MS_PER_SEC 1000 + +// Number of hundred nanosecs per sec. +#define HNS_PER_SEC 10000000 + +// Compatible ID for render/capture +#define ACX_DSP_RENDER_COMPATIBLE_ID L"{ad164f4d-4149-41ed-82e8-99732ed7371a}" + +// Container ID for render/capture +#define ACX_DSP_SYSTEM_CONTAINER_ID L"{00000000-0000-0000-ffff-ffffffffffff}" + + +// Compatible ID for render/capture +#define ACX_DSP_TEST_COMPATIBLE_ID L"{ad164f4d-4149-41ed-82e8-99732ed7371a}" +// Container ID for render/capture +#define ACX_DSP_TEST_CONTAINER_ID L"{00000000-0000-0000-ffff-ffffffffffff}" + +extern const GUID DSP_CIRCUIT_SPEAKER_GUID; +extern const GUID DSP_CIRCUIT_MICROPHONE_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_RENDER_GUID; +extern const GUID DSP_CIRCUIT_UNIVERSALJACK_CAPTURE_GUID; + +extern const GUID SYSTEM_CONTAINER_GUID; + +#undef MIN +#undef MAX +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#define REQUEST_TIMEOUT_SECONDS 5 + +#ifndef SIZEOF_ARRAY +#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) +#endif // !defined(SIZEOF_ARRAY) + +// +// Define DSP driver context. +// +typedef struct _DSP_DRIVER_CONTEXT { + BOOLEAN Dummy; +} DSP_DRIVER_CONTEXT, *PDSP_DRIVER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_DRIVER_CONTEXT, GetDspDriverContext) + +#define ALL_CHANNELS_ID UINT32_MAX +#define MAX_CHANNELS 2 +#define CHANNEL_MASK_INVALID UINT32_MAX + +// +// Define DSP device context. +// +typedef struct _DSP_DEVICE_CONTEXT { + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + ACXFACTORYCIRCUIT Factory; + WDFDEVICE AudioSensorsDevice; + WDFCHILDLIST ChildList; +} DSP_DEVICE_CONTEXT, *PDSP_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_DEVICE_CONTEXT, GetDspDeviceContext) + +// +// Define Audio Sensors device context. +// +typedef struct _AUDIO_SENSORS_DEVICE_CONTEXT +{ + WDFDEVICE Device; +} AUDIO_SENSORS_DEVICE_CONTEXT, *PAUDIO_SENSORS_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(AUDIO_SENSORS_DEVICE_CONTEXT, GetAudioSensorsDeviceContext) + +// +// Define DSP factory context. +// +typedef struct _DSP_FACTORY_CONTEXT { + WDFDEVICE Device; +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + WDFWAITLOCK CacheLock; + WDFCOLLECTION Cache; +#endif +} DSP_FACTORY_CONTEXT, *PDSP_FACTORY_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_FACTORY_CONTEXT, GetDspFactoryContext) + +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 +// +// Define DSP device ID context. +// +typedef struct _DSP_DEVICEID_CONTEXT { + ACXFACTORYCIRCUIT Factory; + GUID UniqueID; +} DSP_DEVICEID_CONTEXT, *PDSP_DEVICEID_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_DEVICEID_CONTEXT, GetDspDeviceIdContext) +#endif // ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + +// +// Define RENDER device context. +// +typedef struct _DSP_RENDER_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} DSP_RENDER_DEVICE_CONTEXT, *PDSP_RENDER_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_RENDER_DEVICE_CONTEXT, GetRenderDeviceContext) + +// Special stream definitions +typedef enum _SDCA_SPECIALSTREAM_TYPE +{ + SpecialStreamTypeNotSupported = 0, + SpecialStreamTypeUltrasoundRender = 1, + SpecialStreamTypeUltrasoundCapture = 2, + SpecialStreamTypeReferenceStream = 3, + SpecialStreamTypeIvSense = 4, + SpecialStreamType_Count = 5, +} SDCA_SPECIALSTREAM_TYPE, *PSDCA_SPECIALSTREAM_TYPE; + +inline const SDCA_SPECIALSTREAM_TYPE SpecialStreamTypeFromSdcaPath(SDCA_PATH path) +{ + switch(path) + { + case SdcaPathUltrasoundRender: + return SpecialStreamTypeUltrasoundRender; + case SdcaPathUltrasoundCapture: + return SpecialStreamTypeUltrasoundCapture; + case SdcaPathReferenceStream: + return SpecialStreamTypeReferenceStream; + case SdcaPathIvSense: + return SpecialStreamTypeIvSense; + } + return SpecialStreamTypeNotSupported; +} + +inline const SDCA_PATH SdcaPathFromSpecialStreamType(SDCA_SPECIALSTREAM_TYPE type) +{ + switch(type) + { + case SpecialStreamTypeUltrasoundRender: + return SdcaPathUltrasoundRender; + case SpecialStreamTypeUltrasoundCapture: + return SdcaPathUltrasoundCapture; + case SpecialStreamTypeReferenceStream: + return SdcaPathReferenceStream; + case SpecialStreamTypeIvSense: + return SdcaPathIvSense; + } + return (SDCA_PATH) 0; +} + +// Maximum of 8 devices chosen for the purpose of making this sample simpler +#define MAX_AGGREGATED_DEVICES (8) + +// +// Define circuit context. +// +typedef struct _DSP_CIRCUIT_CONTEXT { + ULONG EndpointId; + ULONG DataPortNumber; + ACXAUDIOENGINE AudioEngineElement; + ACXPEAKMETER PeakMeterElement; + PVOID peakMeter; + ACXKEYWORDSPOTTER KeywordSpotter; + + // If the VolumeMuteHandler is set, we will forward any + // Volume/Mute requests for the current circuit to this + // target circuit. If the target circuit was allocated + // by this driver, it will also be copied to + // TargetCircuitToDelete + ACXTARGETCIRCUIT TargetCircuitToDelete; + ACXTARGETCIRCUIT TargetVolumeMuteCircuit; + ACXTARGETELEMENT TargetVolumeHandler; + ACXTARGETELEMENT TargetMuteHandler; + + BOOLEAN IsRenderCircuit; + + // This will contain information on the aggregated devices we're connected to + BOOLEAN Aggregated; + ULONG AggregatedDeviceCount; + SDCA_AGGREGATION_DEVICE AggregatedDevices[MAX_AGGREGATED_DEVICES]; + PSDCA_PATH_DESCRIPTORS2 AggregatedPathDescriptors; + + ULONG SpecialStreamAvailablePaths; + PSDCA_PATH_DESCRIPTORS SpecialStreamPathDescriptors[SpecialStreamType_Count]; + PSDCA_PATH_DESCRIPTORS2 SpecialStreamPathDescriptors2[SpecialStreamType_Count]; + ULONG SpecialStreamActive[SpecialStreamType_Count]; + ULONG SpecialStreamRunning[SpecialStreamType_Count]; + ACXTARGETCIRCUIT SpecialStreamTargetCircuit; + // The ConnectedFunctionInformation will be used with SpecialStream logic and also + // for determining appropriate data ports to be used with each connected audio function + PSDCA_FUNCTION_INFORMATION_LIST ConnectedFunctionInformation; + +} DSP_CIRCUIT_CONTEXT, * PDSP_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_CIRCUIT_CONTEXT, GetDspCircuitContext) + +// +// Define CAPTURE device context. +// +typedef struct _DSP_CAPTURE_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} DSP_CAPTURE_DEVICE_CONTEXT, *PDSP_CAPTURE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext) + +// +// Define DSP circuit/stream element context. +// +typedef struct _DSP_ELEMENT_CONTEXT { + BOOLEAN Dummy; +} DSP_ELEMENT_CONTEXT, *PDSP_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_ELEMENT_CONTEXT, GetDspElementContext) + +// +// Define DSP format context. +// +typedef struct _DSP_FORMAT_CONTEXT { + BOOLEAN Dummy; +} DSP_FORMAT_CONTEXT, *PDSP_FORMAT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_FORMAT_CONTEXT, GetDspFormatContext) + +typedef enum _DSP_PIN_TYPE { + DspPinTypeHost, + DspPinTypeOffload, + DspPinTypeLoopback, + DspPinTypeBridge, + DspPinType_Count +} DSP_PIN_TYPE, * PDSP_PIN_TYPE; + +typedef enum _DSP_CAPTURE_PIN_TYPE { + DspCapturePinTypeHost, + DspCapturePinTypeKeyword, + DspCapturePinTypeBridge, + DspCapturePinType_Count +} DSP_CAPTURE_PIN_TYPE, * PDSP_CAPTURE_PIN_TYPE; + +typedef struct _DSP_PIN_CONTEXT { + ACXTARGETCIRCUIT TargetCircuit; + ULONG TargetPinId; + DSP_PIN_TYPE PinType; + DSP_CAPTURE_PIN_TYPE CapturePinType; + + // The stream bridge below will only be valid for the Capture circuit Bridge Pin + + // Host stream bridge will be used to ensure host stream creations are passed + // to the downlevel circuits. Since the HostStreamBridge won't have InModes set, + // the ACX framework will not add streams automatically. We will add streams for + // non KWS pin. + ACXSTREAMBRIDGE HostStreamBridge; + ACXOBJECTBAG HostStreamObjBag; + +#ifdef ACX_WORKAROUND_ACXPIN_01 + ULONG MaxStreams; + ULONG CurrentStreamsCount; +#endif +} DSP_PIN_CONTEXT, *PDSP_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PIN_CONTEXT, GetDspPinContext) + +// +// Define DSP render/capture stream context. +// +typedef struct _DSP_STREAM_CONTEXT { + PVOID StreamEngine; + DSP_PIN_TYPE PinType; + DSP_CAPTURE_PIN_TYPE CapturePinType; + ACXPIN Pin; // used by acx workaround, and reference streams + +#ifdef ACX_WORKAROUND_ACXPIN_01 + BOOLEAN StreamIsCounted; // TRUE = stream is counted on the pin. +#endif + + ACXTARGETCIRCUIT SpecialStreamTargetCircuit; + BOOLEAN SpecialStreamInUse[SpecialStreamType_Count]; + BOOLEAN SpecialStreamRunning[SpecialStreamType_Count]; +} DSP_STREAM_CONTEXT, *PDSP_STREAM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_STREAM_CONTEXT, GetDspStreamContext) + +typedef struct _DSP_ENGINE_CONTEXT { + ACXDATAFORMAT MixFormat; + BOOLEAN GFxEnabled; +} DSP_ENGINE_CONTEXT, * PDSP_ENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_ENGINE_CONTEXT, GetDspEngineContext) + +typedef struct _DSP_STREAMAUDIOENGINE_CONTEXT { + BOOLEAN LFxEnabled; +} DSP_STREAMAUDIOENGINE_CONTEXT, * PDSP_STREAMAUDIOENGINE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_STREAMAUDIOENGINE_CONTEXT, GetDspStreamAudioEngineContext) + +// +// Define DSP keyword spotter context +// +typedef struct _DSP_KEYWORDSPOTTER_CONTEXT { + ACXPNPEVENT Event; + PVOID KeywordDetector; +} DSP_KEYWORDSPOTTER_CONTEXT, *PDSP_KEYWORDSPOTTER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_KEYWORDSPOTTER_CONTEXT, GetDspKeywordSpotterContext) + +typedef struct _DSP_PNPEVENT_CONTEXT { + BOOLEAN Dummy; +} DSP_PNPEVENT_CONTEXT, *PDSP_PNPEVENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PNPEVENT_CONTEXT, GetDspPnpEventContext) + +// +// Define DSP peakmeter element context. +// +typedef struct _DSP_PEAKMETER_ELEMENT_CONTEXT { + PVOID peakMeter; +} DSP_PEAKMETER_ELEMENT_CONTEXT, * PDSP_PEAKMETER_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_PEAKMETER_ELEMENT_CONTEXT, GetDspPeakMeterElementContext) + +#define PEAKMETER_STEPPING_DELTA 0x1000 +#define PEAKMETER_MAXIMUM LONG_MAX +#define PEAKMETER_MINIMUM LONG_MIN + +// +// Define DSP circuit/stream element context. +// +typedef struct _DSP_MUTE_ELEMENT_CONTEXT { + BOOL MuteState[MAX_CHANNELS]; +} DSP_MUTE_ELEMENT_CONTEXT, * PDSP_MUTE_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_MUTE_ELEMENT_CONTEXT, GetDspMuteElementContext) + +// +// Define DSP circuit/stream element context. +// +typedef struct _DSP_VOLUME_ELEMENT_CONTEXT { + LONG VolumeLevel[MAX_CHANNELS]; +} DSP_VOLUME_ELEMENT_CONTEXT, * PDSP_VOLUME_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DSP_VOLUME_ELEMENT_CONTEXT, GetDspVolumeElementContext) + +#define VOLUME_STEPPING 0x8000 +#define VOLUME_LEVEL_MAXIMUM 0x00000000 +#define VOLUME_LEVEL_MINIMUM (-96 * 0x10000) + +// +// Driver prototypes. +// +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_UNLOAD Dsp_DriverUnload; +EVT_WDF_DRIVER_DEVICE_ADD Dsp_EvtBusDeviceAdd; +EVT_WDF_CHILD_LIST_CREATE_DEVICE Dsp_AddAudioSensorsDevice; + +// Device callbacks. + +EVT_WDF_DEVICE_PREPARE_HARDWARE Dsp_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE Dsp_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Dsp_EvtDeviceContextCleanup; + +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE Dsp_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT Dsp_EvtAcxFactoryCircuitCreateCircuit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Dsp_EvtFactoryContextCleanup; +EVT_WDF_DEVICE_CONTEXT_DESTROY Dsp_EvtFactoryContextDestroy; + +// Stream callbacks shared between Capture and Render + +EVT_WDF_OBJECT_CONTEXT_DESTROY Dsp_EvtStreamContextDestroy; +EVT_ACX_STREAM_GET_HW_LATENCY Dsp_EvtStreamGetHwLatency; +EVT_ACX_STREAM_ALLOCATE_RTPACKETS Dsp_EvtStreamAllocateRtPackets; +EVT_ACX_STREAM_FREE_RTPACKETS Dsp_EvtStreamFreeRtPackets; +EVT_ACX_STREAM_PREPARE_HARDWARE Dsp_EvtStreamPrepareHardware; +EVT_ACX_STREAM_RELEASE_HARDWARE Dsp_EvtStreamReleaseHardware; +EVT_ACX_STREAM_RUN Dsp_EvtStreamRun; +EVT_ACX_STREAM_PAUSE Dsp_EvtStreamPause; +EVT_ACX_STREAM_GET_CURRENT_PACKET Dsp_EvtStreamGetCurrentPacket; +EVT_ACX_STREAM_ASSIGN_DRM_CONTENT_ID Dsp_EvtStreamAssignDrmContentId; +EVT_ACX_STREAM_GET_PRESENTATION_POSITION Dsp_EvtStreamGetPresentationPosition; +EVT_ACX_OBJECT_PREPROCESS_REQUEST DspC_EvtStreamRequestPreprocess; + + +// Render callbacks. +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE DspR_EvtAcxFactoryCircuitCreateCircuitDevice; + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +NTAPI +DspR_EvtAcxFactoryCircuitCreateCircuit( + _In_ + WDFDEVICE Parent, + _In_ + WDFDEVICE Device, + _In_ + ACXFACTORYCIRCUIT Factory, + _In_ + PACX_FACTORY_CIRCUIT_ADD_CIRCUIT Config, + _In_ + PACXCIRCUIT_INIT CircuitInit, + _In_ + ULONG DataPortNumber, + _In_opt_ + PSDCA_PATH_DESCRIPTORS2 PathDescriptors +); + +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE DspR_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE DspR_EvtCircuitCompositeInitialize; + +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspR_EvtCircuitContextCleanup; +EVT_WDF_DEVICE_PREPARE_HARDWARE DspR_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE DspR_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DspR_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspR_EvtDeviceContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST DspR_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM DspR_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP DspR_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN DspR_EvtCircuitPowerDown; +EVT_ACX_STREAM_SET_RENDER_PACKET DspR_EvtStreamSetRenderPacket; +EVT_ACX_PIN_SET_DATAFORMAT DspR_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspR_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED DspR_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED DspR_EvtPinDisconnected; + +//Render Audio Engine +EVT_ACX_MUTE_ASSIGN_STATE DspR_EvtMuteAssignState; +EVT_ACX_MUTE_RETRIEVE_STATE DspR_EvtMuteRetrieveState; +EVT_ACX_VOLUME_ASSIGN_LEVEL DspR_EvtVolumeAssignLevel; +EVT_ACX_VOLUME_RETRIEVE_LEVEL DspR_EvtVolumeRetrieveLevel; +EVT_ACX_PEAKMETER_RETRIEVE_LEVEL DspR_EvtPeakMeterRetrieveLevelCallback; +EVT_ACX_RAMPED_VOLUME_ASSIGN_LEVEL DspR_EvtRampedVolumeAssignLevel; +EVT_ACX_AUDIOENGINE_RETRIEVE_BUFFER_SIZE_LIMITS DspR_EvtAcxAudioEngineRetrieveBufferSizeLimits; +EVT_ACX_AUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxAudioEngineRetrieveEffectsState; +EVT_ACX_AUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxAudioEngineAssignEffectsState; +EVT_ACX_AUDIOENGINE_RETRIEVE_ENGINE_FORMAT DspR_EvtAcxAudioEngineRetrieveEngineMixFormat; +EVT_ACX_AUDIOENGINE_ASSIGN_ENGINE_FORMAT DspR_EvtAcxAudioEngineAssignEngineDeviceFormat; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineRetrieveEffectsState; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_EFFECTS_STATE DspR_EvtAcxStreamAudioEngineAssignEffectsState; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_PRESENTATION_POSITION DspR_EvtAcxStreamAudioEngineRetrievePresentationPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_CURRENT_WRITE_POSITION DspR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; +EVT_ACX_STREAMAUDIOENGINE_RETRIEVE_LINEAR_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LAST_BUFFER_POSITION DspR_EvtAcxStreamAudioEngineAssignLastBufferPosition; +EVT_ACX_STREAMAUDIOENGINE_ASSIGN_LOOPBACK_PROTECTION DspR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + +// Capture callbacks. +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE DspC_EvtAcxFactoryCircuitCreateCircuitDevice; + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +NTAPI +DspC_EvtAcxFactoryCircuitCreateCircuit( + _In_ + WDFDEVICE Parent, + _In_ + WDFDEVICE Device, + _In_ + ACXFACTORYCIRCUIT Factory, + _In_ + PACX_FACTORY_CIRCUIT_ADD_CIRCUIT Config, + _In_ + PACXCIRCUIT_INIT CircuitInit, + _In_ + ULONG DataPortNumber, + _In_ + PSDCA_PATH_DESCRIPTORS2 PathDescriptors +); + +EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE DspC_EvtCircuitCompositeCircuitInitialize; +EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE DspC_EvtCircuitCompositeInitialize; + +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspC_EvtCircuitContextCleanup; +EVT_WDF_DEVICE_PREPARE_HARDWARE DspC_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE DspC_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DspC_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspC_EvtDeviceContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST DspC_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM DspC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP DspC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN DspC_EvtCircuitPowerDown; +EVT_ACX_STREAM_GET_CAPTURE_PACKET DspC_EvtStreamGetCapturePacket; +EVT_ACX_PIN_SET_DATAFORMAT DspC_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP DspC_EvtPinContextCleanup; +EVT_ACX_PIN_CONNECTED DspC_EvtPinConnected; +EVT_ACX_PIN_DISCONNECTED DspC_EvtPinDisconnected; +EVT_ACX_KEYWORDSPOTTER_RETRIEVE_ARM DspC_EvtAcxKeywordSpotterRetrieveArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_ARM DspC_EvtAcxKeywordSpotterAssignArm; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_PATTERNS DspC_EvtAcxKeywordSpotterAssignPatterns; +EVT_ACX_KEYWORDSPOTTER_ASSIGN_RESET DspC_EvtAcxKeywordSpotterAssignReset; + +// Property testing, todo: remove them. + +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinCInstancesCallback; +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinCTypesCallback; +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinDataFlowCallback; +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinDataRangesCallback; +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinDataIntersectionCallback; +EVT_ACX_OBJECT_PROCESS_REQUEST DspR_EvtPinPhysicalConnectionCallback; + + +EVT_ACX_OBJECT_PREPROCESS_REQUEST DspR_EvtStreamRequestPreprocess; +EVT_WDF_OBJECT_CONTEXT_CLEANUP Dsp_EvtStreamContextCleanup; + +#ifdef ACX_WORKAROUND_ACXPIN_01 +EVT_ACX_OBJECT_PREPROCESS_REQUEST Dsp_EvtStreamGetStreamCountRequestPreprocess; +#endif // ACX_WORKAROUND_ACXPIN_01 + +#ifdef ACX_WORKAROUND_ACXPIN_02 +EVT_ACX_OBJECT_PREPROCESS_REQUEST Dsp_EvtStreamProposeDataFormatRequestPreprocess; +#endif // ACX_WORKAROUND_ACXPIN_02 + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +// +// Used to store the registry settings path for the driver +// +extern UNICODE_STRING g_RegistryPath; + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath + ); + +PAGED_CODE_SEG +NTSTATUS +Dsp_CreateChildList( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +Dsp_AddFactoryCircuit( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +VOID +Dsp_RemoveFactoryCircuit( + _In_ WDFDEVICE Device +); + +#ifdef ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 +PAGED_CODE_SEG +NTSTATUS +Dsp_InitializeChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ); + +PAGED_CODE_SEG +VOID +Dsp_CleanupChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ); + +PAGED_CODE_SEG +VOID +Dsp_DeleteChildDevicesCache( + _In_ ACXFACTORYCIRCUIT Factory + ); + +PAGED_CODE_SEG +bool +Dsp_IsChildDeviceInCacheLocked( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId + ); + +PAGED_CODE_SEG +NTSTATUS +Dsp_AddChildDeviceToCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId, + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +WDFDEVICE +Dsp_RemoveChildDeviceFromCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ const GUID * UniqueId + ); + +PAGED_CODE_SEG +VOID +Dsp_PurgeChildDeviceFromCache( + _In_ ACXFACTORYCIRCUIT Factory, + _In_ WDFDEVICE Device + ); + +EVT_ACX_OBJECT_PREPROCESS_REQUEST Dsp_EvtFactoryRemoveCircuitRequestPreprocess; +EVT_WDF_DEVICE_CONTEXT_CLEANUP Dsp_EvtDeviceIdContextCleanup; +EVT_ACX_OBJECT_PROCESS_REQUEST Dsp_EvtFactoryCircuitRemoveCircuitCallback; +#endif // ACX_WORKAROUND_ACXFACTORYCIRCUIT_01 + +PAGED_CODE_SEG +NTSTATUS +DspC_CircuitCleanup( + _In_ ACXCIRCUIT Device + ); + +PAGED_CODE_SEG +NTSTATUS +Dsp_SetPowerPolicy( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +DspR_SetPowerPolicy( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +DspC_SetPowerPolicy( + _In_ WDFDEVICE Device + ); + +PAGED_CODE_SEG +NTSTATUS +DSP_SendPropertyTo +( + _In_ WDFDEVICE Device, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information +); + +PAGED_CODE_SEG +NTSTATUS +Dsp_SendTestPropertyTo( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information + ); + +PAGED_CODE_SEG +VOID +Dsp_SendVendorSpecificProperties( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ BOOLEAN SetValue + ); + + +// Create a single SDCA_PATH for special streaming associated +// with the given ACXSTREAM +PAGED_CODE_SEG +NTSTATUS +Dsp_PrepareSpecialStreamForStream( + _In_ ACXSTREAM Stream, + _In_ SDCA_SPECIALSTREAM_TYPE SpecialStreamType, + _In_ ULONG FunctionBitMask = 0xffffffff + ); + +// Destroy all SDCA_PATHs associated with the given ACXSTREAM +PAGED_CODE_SEG +NTSTATUS +Dsp_ReleaseSpecialStreamsForStream( + _In_ ACXSTREAM Stream + ); + +// Start all SDCA_PATHs associated with the given ACXSTREAM +PAGED_CODE_SEG +NTSTATUS +Dsp_StartSpecialStreamsForStream( + _In_ ACXSTREAM Stream + ); + +// Stop all SDCA_PATHs associated with the given ACXSTREAM +PAGED_CODE_SEG +NTSTATUS +Dsp_StopSpecialStreamsForStream( + _In_ ACXSTREAM Stream + ); + +#endif // _PRIVATE_H_ + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/render.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/render.cpp new file mode 100644 index 00000000..fe16d5c4 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/render.cpp @@ -0,0 +1,2730 @@ +/*++ + + 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: + + render.cpp + +Abstract: + + Render factory and circuit + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" +#include "offloadStreamEngine.h" +#include "SimPeakMeter.h" +#include "CircuitHelper.h" +#include "AcpiReader.h" + +#include "TestProperties.h" +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "render.tmh" +#endif + +#include "audiomodule.h" + +using namespace ACPIREADER; + +// +// max # of streams for each pin type. +// +#define DSPR_MAX_INPUT_HOST_STREAMS 2 +#define DSPR_MAX_INPUT_OFFLOAD_STREAMS 3 +#define DSPR_MAX_OUTPUT_LOOPBACK_STREAMS 1 + +// +// Factory circuit IDs. +// +#define RENDER_DEVICE_ID_STR L"{4DCB0606-6415-4A36-BDC5-9B1792117DC9}\\Render&CP_%wZ" +DECLARE_CONST_UNICODE_STRING(RenderHardwareId, L"{4DCB0606-6415-4A36-BDC5-9B1792117DC9}\\Render"); + +DECLARE_CONST_UNICODE_STRING(RenderCompatibleId, ACX_DSP_TEST_COMPATIBLE_ID); +DECLARE_CONST_UNICODE_STRING(RenderContainerId, ACX_DSP_TEST_CONTAINER_ID); +DECLARE_CONST_UNICODE_STRING(RenderDeviceLocation, L"SDCAVDsp Dynamic Enum Speaker"); + +PAGED_CODE_SEG +VOID +DspR_EvtPinCInstancesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +DspR_EvtPinCTypesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +DspR_EvtPinDataFlowCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +DspR_EvtPinDataRangesCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +VOID +DspR_EvtPinDataIntersectionCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request + ) +{ + PAGED_CODE(); + + // TEMP: for testing only. + UNREFERENCED_PARAMETER(Object); + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxPinSetDataFormat ( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +PAGED_CODE_SEG +NTSTATUS +DSP_SendPropertyTo +( + _In_ WDFDEVICE Device, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ GUID PropertySet, + _In_ ULONG PropertyId, + _In_ ACX_PROPERTY_VERB Verb, + _In_ PVOID Control, + _In_ ULONG ControlCb, + _Inout_ PVOID Value, + _In_ ULONG ValueCb, + _Out_ ULONG_PTR* Information +) +{ + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS requestParams; + ACX_REQUEST_PARAMETERS_INIT_PROPERTY( + &requestParams, + PropertySet, + PropertyId, + Verb, + AcxItemTypeCircuit, + 0, + Control, ControlCb, + Value, ValueCb + ); + + WDFREQUEST request; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = Device; + RETURN_NTSTATUS_IF_FAILED(WdfRequestCreate(&attributes, AcxTargetCircuitGetWdfIoTarget(TargetCircuit), &request)); + + auto request_free = scope_exit([&request]() { + WdfObjectDelete(request); + }); + + RETURN_NTSTATUS_IF_FAILED(AcxTargetCircuitFormatRequestForProperty(TargetCircuit, request, &requestParams)); + + WDF_REQUEST_SEND_OPTIONS sendOptions; + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(5)); + + RETURN_NTSTATUS_IF_TRUE(!WdfRequestSend(request, AcxTargetCircuitGetWdfIoTarget(TargetCircuit), &sendOptions), STATUS_INVALID_DEVICE_REQUEST); + + NTSTATUS status = WdfRequestGetStatus(request); + if (Information) + { + *Information = WdfRequestGetInformation(request); + } + if (status == STATUS_BUFFER_OVERFLOW && ValueCb == 0) + { + // Don't trace this error, it's normal + return status; + } + + RETURN_NTSTATUS_IF_FAILED(status); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_AssignAggregatedDataPorts( + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin + ) +{ + NTSTATUS status = STATUS_SUCCESS; + const ULONG MAX_EXPECTED_AGGREGATED_DEVICES = 16; + // There will be one data port in this array for each aggregated device. + ULONG dataPortPerFunction[MAX_EXPECTED_AGGREGATED_DEVICES]; + ULONG dataPortPerFunctionCount = 0; + struct DataPortMap + { + ULONG FunctionId; + ULONG DataPortNumber; + }; + + // This is an example of one way the Function ID could be used to determine which data port should be used + // Note that the order of the Audio Functions is not determistic. We will recalculate the data port array + // each time our circuit's pin is connected to the aggregator's pin. + // Note that until the pin connection is made there is no way to determine what order the audio functions + // will be indexed by. + // + // In most or all cases for real-world drivers, this information should be loaded from the ACPI audio composition + // tables as an array of mappings between Function ID and Data Port. In the case of conflicting Function IDs the + // streaming driver could also include FunctionManufacturerId when determining which data port to use. + DataPortMap dataPortMapping[] = + { + {0x6798, 0x1}, // Example Function ID of 6798 + {0x5037, 0x3}, // Example Function ID of 5037 + }; + + DSP_PIN_CONTEXT* pinCtx = GetDspPinContext(Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(Circuit); + + PAGED_CODE(); + + if (circuitCtx->ConnectedFunctionInformation && + circuitCtx->ConnectedFunctionInformation->FunctionCount >= 1) + { + // The DataPortNumbers entry is required for aggregated systems that use different data port numbers for each + // connected audio function. + // The DataPortNumbers entry can also be used for non-aggregated systems, where the single value will be used + // instead of DPNo. + // For aggregated systems that use the same data port number for each connected audio function, DataPortNumbers + // must still have one entry for each audio function if it is used. + for (ULONG i = 0; i < circuitCtx->ConnectedFunctionInformation->FunctionCount; ++i) + { + // For each of the devices that's being aggregated, we will determine if we have a data port for the device + // in the mapping. If so, we will assign that data port to the device's index in the array of data ports we + // will add to the VarArguments for the stream bridge. + + for (ULONG mapIdx = 0; mapIdx < ARRAYSIZE(dataPortMapping); ++mapIdx) + { + if (dataPortMapping[mapIdx].FunctionId == circuitCtx->ConnectedFunctionInformation->FunctionInfoList[i].FunctionId) + { + // The Audio Function at index 'i' has the same Function Id as this mapping entry. + dataPortPerFunction[i] = dataPortMapping[mapIdx].DataPortNumber; + + // We want to ensure we have a data port in our map for each audio function + ++dataPortPerFunctionCount; + break; + } + } + } + } + + ASSERT((dataPortPerFunctionCount == 0) || (dataPortPerFunctionCount == circuitCtx->ConnectedFunctionInformation->FunctionCount)); + + if ((dataPortPerFunctionCount > 0) && (dataPortPerFunctionCount == circuitCtx->ConnectedFunctionInformation->FunctionCount)) + { + // The SdcaAggregator driver will override DPNo for each aggregated device with the value in that device's index in the + // DataPortNumbers array. + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DataPortNumbers); + WDFMEMORY dataPortMemory = nullptr; + + RETURN_NTSTATUS_IF_FAILED(WdfMemoryCreatePreallocated(nullptr, dataPortPerFunction, sizeof(ULONG)* dataPortPerFunctionCount, &dataPortMemory)); + auto dataPortMemory_free = scope_exit([&dataPortMemory]() + { + WdfObjectDelete(dataPortMemory); + }); + + // Add the DataPortNumbers to the AcxObjectBag that was assigned to the Stream Bridge during circuit creation. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddBlob(pinCtx->HostStreamObjBag, &DataPortNumbers, dataPortMemory)); + } + else if (dataPortPerFunctionCount > 0) + { + status = STATUS_DEVICE_CONFIGURATION_ERROR; + DrvLogError(g_SDCAVDspLog, FLAG_INFO, L"Found aggregated data port entry, but not for every audio function, %!STATUS!", status); + } + // If dataPortPerFunctionCount is 0, there aren't specific data ports per audio function and SdcaAggregator can leave DPNo as is for + // each of the different audio functions. + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_AssignAggregatedPathDescriptors( + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin +) +{ + WDFMEMORY descriptorsMemory = nullptr; + PSDCA_PATH_DESCRIPTORS2 descriptorsBuffer = nullptr; + + DSP_PIN_CONTEXT* pinCtx = GetDspPinContext(Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(Circuit); + + PAGED_CODE(); + + if (circuitCtx->AggregatedPathDescriptors == nullptr) + { + return STATUS_SUCCESS; + } + + // Note that in the companion amp scenario some DSP drivers may not include aggregated path descriptor information + // for the companion amps. In that case, the connected function information count (which includes companions) + // will be more than the desciptor count. + if (!circuitCtx->ConnectedFunctionInformation || + circuitCtx->ConnectedFunctionInformation->FunctionCount < circuitCtx->AggregatedPathDescriptors->DescriptorCount) + { + return STATUS_SUCCESS; + } + + RETURN_NTSTATUS_IF_FAILED(WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, NonPagedPoolNx, DRIVER_TAG, circuitCtx->AggregatedPathDescriptors->Size, &descriptorsMemory, (PVOID*)&descriptorsBuffer)); + auto free_memory = scope_exit([&descriptorsMemory]() + { + WdfObjectDelete(descriptorsMemory); + }); + + // Copy over entirely; we'll fix up the Function Information Id inplace + RtlCopyMemory(descriptorsBuffer, circuitCtx->AggregatedPathDescriptors, circuitCtx->AggregatedPathDescriptors->Size); + + ULONG fixedUpDescriptors = 0; + for (ULONG i = 0; i < circuitCtx->AggregatedPathDescriptors->DescriptorCount; ++i) + { + // For each of the aggregated devices, we need look it up by the UniqueID in the list of path descriptors + // we have. + for (ULONG connected = 0; connected < circuitCtx->ConnectedFunctionInformation->FunctionCount; ++connected) + { + // When saving the aggregated path descriptors, we stored the Function Info Unique ID in the descriptor's FunctionInformationId + // We use the Function Info Unique ID here to determine the correct FunctionInformationId for the aggregated device. + // The order of the aggregated devices can change depending on a lot of factors, so we need to use the Unique ID to get the right + // FunctionInformationId for each device. + if (circuitCtx->AggregatedPathDescriptors->Descriptor[i].FunctionInformationId == circuitCtx->ConnectedFunctionInformation->FunctionInfoList[connected].UniqueId) + { + descriptorsBuffer->Descriptor[i].FunctionInformationId = circuitCtx->ConnectedFunctionInformation->FunctionInfoList[connected].FunctionInformationId; + ++fixedUpDescriptors; + break; + } + } + } + + if (fixedUpDescriptors != descriptorsBuffer->DescriptorCount) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_DEVICE_CONFIGURATION_ERROR); + } + + descriptorsBuffer->EndpointId = circuitCtx->EndpointId; + + // Add the DataPortNumbers to the AcxObjectBag that was assigned to the Stream Bridge during circuit creation. + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddBlob(pinCtx->HostStreamObjBag, &SdcaPropertyPathDescriptors2, descriptorsMemory)); + + return STATUS_SUCCESS; +} + + + +// +// This callback is called when the Circuit bridge pin is connected to +// bridge pin of another circuit. +// +// This will happen when the composite circuit is fully initialized. +// From this point onwards the TargetCircuit can be used to send +// KSPROPERTY requests +// +// params: +// TargetCircuit - ACX wrapper for WDFIOTARGET for the connected circuit +// TargetPinId - The pin on the connected circuit. This can be used to +// send pin specific KSPROPERTY requests. +// +PAGED_CODE_SEG +VOID +DspR_EvtPinConnected ( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId + ) +{ + PAGED_CODE(); + + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(Pin); + pinCtx->TargetCircuit = TargetCircuit; + pinCtx->TargetPinId = TargetPinId; + + // The bridge pin should support the same formats that are supported by the downstream circuit + // We could also change the formats supported by the host pin here, but a DSP will typically determine + // those formats and do appropriate processing. + ACXPIN bridgePin = AcxCircuitGetPinById(AcxPinGetCircuit(Pin), DspPinTypeBridge); + NTSTATUS status = ReplicateFormatsForPin(bridgePin, TargetCircuit, TargetPinId); + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVDspLog, FLAG_STREAM, L"Failed to replicate downstream formats to bridge pin, %!STATUS!", + status); + } + + ACXAUDIOENGINE audioEngine = GetDspCircuitContext(AcxPinGetCircuit(Pin))->AudioEngineElement; + status = ReplicateFormatsForAudioEngine(audioEngine, TargetCircuit, TargetPinId); + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVDspLog, FLAG_STREAM, L"Failed to replicate downstream formats to audio engine, %!STATUS!", + status); + } + + // The ACX framework will maintain the TargetCircuit until after it's called EvtPinDisconnected + + ACXCIRCUIT circuit = AcxPinGetCircuit(Pin); + status = FindDownstreamVolumeMute(circuit, TargetCircuit); + if (!NT_SUCCESS(status)) + { + DrvLogWarning(g_SDCAVDspLog, FLAG_INIT, L"Unable to find downstream volume/mute elements. Volume and Mute forwarding will be disabled. %!STATUS!", status); + } + + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + + // Preallocate enough room to hold information for maximum expected aggregated devices. + struct AggregationDevices + { + SDCA_AGGREGATION_DEVICES Devices; + SDCA_AGGREGATION_DEVICE DeviceExtra[MAX_AGGREGATED_DEVICES-1]; + }; + AggregationDevices aggDevices{ 0 }; + aggDevices.Devices.Size = sizeof(aggDevices); + // The DSP driver should know from the ACPI composition tables whether + // this circuit is connected to an aggregated endpoint. However, in the + // meantime, we will just ask the target circuit. + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_SdcaAgg, + KSPROPERTY_SDCAAGG_AGGREGATED_DEVICES, + AcxPropertyVerbGet, + nullptr, 0, + &aggDevices, + sizeof(aggDevices), + nullptr + ); + + if (NT_SUCCESS(status)) + { + circuitCtx->Aggregated = TRUE; + circuitCtx->AggregatedDeviceCount = aggDevices.Devices.FunctionCount; + for (ULONG i = 0; i < aggDevices.Devices.FunctionCount; ++i) + { + RtlCopyMemory(&circuitCtx->AggregatedDevices[i], &aggDevices.Devices.FunctionIds[i], sizeof(SDCA_AGGREGATION_DEVICE)); + } + } + + // Delete previous ConnectedFunctionInformation if any is already allocated + if (circuitCtx->ConnectedFunctionInformation) + { + ExFreePool(circuitCtx->ConnectedFunctionInformation); + circuitCtx->ConnectedFunctionInformation = nullptr; + } + + ULONG_PTR requiredBufferSize; + + // retrieve the function information for this device. We'll use this information if the device + // has special stream capabilities. + // We'll also use this information if this is an aggregated device that has different Data Port requirements for the audio functions. + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_FUNCTION_INFORMATION, + AcxPropertyVerbGet, + nullptr, 0, + nullptr, 0, + &requiredBufferSize); + + if (status == STATUS_BUFFER_OVERFLOW && + requiredBufferSize >= sizeof(SDCA_FUNCTION_INFORMATION_LIST)) + { + circuitCtx->ConnectedFunctionInformation = (PSDCA_FUNCTION_INFORMATION_LIST)ExAllocatePool2(POOL_FLAG_NON_PAGED, requiredBufferSize, DRIVER_TAG); + if (!circuitCtx->ConnectedFunctionInformation) + { + return; + } + + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_FUNCTION_INFORMATION, + AcxPropertyVerbGet, + nullptr, 0, + circuitCtx->ConnectedFunctionInformation, (ULONG)requiredBufferSize, + nullptr); + } + + if (circuitCtx->ConnectedFunctionInformation && circuitCtx->ConnectedFunctionInformation->FunctionCount > 1) + { + // Since FunctionCount is > 1, this is an aggregated system. As such we should update the stream bridge's VarArguments Bag + // to include a list of data ports based on the devices being aggregated. + // This is necessary if the aggregated audio functions are not uniform and use different data ports for their inputs. + status = DspR_AssignAggregatedDataPorts(circuit, Pin); + if (!NT_SUCCESS(status)) + { + DrvLogWarning(g_SDCAVDspLog, FLAG_INIT, L"Unable to assign data ports for aggregated connection. %!STATUS!", status); + } + + // To specify channel mask or more information, the path descriptors structure needs to be used + status = DspR_AssignAggregatedPathDescriptors(circuit, Pin); + if (!NT_SUCCESS(status)) + { + DrvLogWarning(g_SDCAVDspLog, FLAG_INIT, L"Unable to assign path descriptors for aggregated connection. %!STATUS!", status); + } + } + + // retrieve the special stream capabilities for the downstream device + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_FUNCTION_CAPABILITY, + AcxPropertyVerbGet, + NULL, 0, + &circuitCtx->SpecialStreamAvailablePaths, sizeof(SDCA_PATH), + nullptr); + + if (NT_SUCCESS(status)) + { + // we have path information for a target circuit which supports + // special paths. collect/refresh our cached information. + if (circuitCtx->SpecialStreamTargetCircuit) + { + // ACX will not call EvtPinConnected more than once without + // calling EvtPinDisconnected between, so SpecialStreamTargetCircuit + // should be NULL here. + ASSERT(FALSE); + } + + // Since we'll clean this up in EvtPinDisconnected we do not + // need to perform WdfObjectReference on the TargetCircuit here. + circuitCtx->SpecialStreamTargetCircuit = TargetCircuit; + + for(ULONG i = (UINT) SpecialStreamTypeUltrasoundRender; i < (UINT) SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors[i]); + circuitCtx->SpecialStreamPathDescriptors[i] = nullptr; + } + } + } + + // go through the capabilities and query each that is supported for the descriptors + for(ULONG i = (UINT) SpecialStreamTypeUltrasoundRender; i < (UINT) SpecialStreamType_Count; i++) + { + SDCA_PATH currentPath = SdcaPathFromSpecialStreamType((SDCA_SPECIALSTREAM_TYPE) i); + + if ((circuitCtx->SpecialStreamAvailablePaths & currentPath) != 0) + { + // The descriptor is a variable length structure, so + // we need to first determine the size required + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_PATH_DESCRIPTORS, + AcxPropertyVerbGet, + ¤tPath, sizeof(SDCA_PATH), + nullptr, 0, + &requiredBufferSize); + + // buffer overflow indicates that the descriptorSize has been filled in with + // the required buffer size. It should be at least a SDCA_PATH_DESCRIPTORS worth + // of data, more depending on formats supported. + if (status == STATUS_BUFFER_OVERFLOW && + requiredBufferSize >= sizeof(SDCA_PATH_DESCRIPTORS)) + { + // now that we know the size, allocate and retrieve it. + circuitCtx->SpecialStreamPathDescriptors[i] = (PSDCA_PATH_DESCRIPTORS) ExAllocatePool2(POOL_FLAG_NON_PAGED, requiredBufferSize, DRIVER_TAG); + if (circuitCtx->SpecialStreamPathDescriptors[i]) + { + status = DSP_SendPropertyTo( + AcxCircuitGetWdfDevice(circuit), + TargetCircuit, + KSPROPERTYSETID_Sdca, + KSPROPERTY_SDCA_PATH_DESCRIPTORS, + AcxPropertyVerbGet, + ¤tPath, sizeof(SDCA_PATH), + circuitCtx->SpecialStreamPathDescriptors[i], (ULONG) requiredBufferSize, + nullptr); + } + } + } + } +} + +// +// This callback is called when the Circuit bridge pin is disconnected +// from the bridge pin of another circuit. +// +// This will happen when the composite circuit is deinitialized. +// From this point onwards the TargetCircuit cannnot be used to send +// KSPROPERTY requests. +// TargetCircuit should only be used to access the attached context. +// +// params: +// TargetCircuit - ACX wrapper for WDFIOTARGET for the connected circuit +// TargetPinId - The pin on the connected circuit. +// +PAGED_CODE_SEG +VOID +DspR_EvtPinDisconnected ( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(TargetPinId); + UNREFERENCED_PARAMETER(TargetCircuit); + + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(Pin); + + // We cannot use the TargetCircuit after returning from EvtPinDisconnected + if (pinCtx->TargetCircuit) + { + pinCtx->TargetCircuit = NULL; + pinCtx->TargetPinId = (ULONG)(-1); + } + + ACXCIRCUIT circuit = AcxPinGetCircuit(Pin); + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(circuit); + if (circuitCtx->TargetVolumeMuteCircuit) + { + circuitCtx->TargetMuteHandler = nullptr; + circuitCtx->TargetVolumeHandler = nullptr; + circuitCtx->TargetVolumeMuteCircuit = nullptr; + } + if (circuitCtx->TargetCircuitToDelete) + { + WdfObjectDelete(circuitCtx->TargetCircuitToDelete); + circuitCtx->TargetCircuitToDelete = nullptr; + } + + circuitCtx->SpecialStreamAvailablePaths = 0; + + for(ULONG i = (UINT) SpecialStreamTypeUltrasoundRender; i < (UINT) SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors[i]); + circuitCtx->SpecialStreamPathDescriptors[i] = nullptr; + } + } + + if (circuitCtx->SpecialStreamTargetCircuit) + { + circuitCtx->SpecialStreamTargetCircuit = nullptr; + } + + if (circuitCtx->ConnectedFunctionInformation) + { + ExFreePool(circuitCtx->ConnectedFunctionInformation); + circuitCtx->ConnectedFunctionInformation = nullptr; + } +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated + ) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PDSP_RENDER_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP %p Prepare Hardware, First Time %d", Device, devCtx->FirstTimePrepareHardware); + + if (!devCtx->FirstTimePrepareHardware) + { + // + // This is a rebalance. Validate the circuit resources and + // if needed, delete and re-create the circuit. + // The sample driver doens't use resources, thus the existing + // circuits are kept. + // + status = STATUS_SUCCESS; + return status; + } + + // + // Set child's power policy. + // + RETURN_NTSTATUS_IF_FAILED(DspR_SetPowerPolicy(Device)); + + // + // Add circuit to child's list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Circuit)); + + // + // Keep track this is not the first time this callback was called. + // + devCtx->FirstTimePrepareHardware = FALSE; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated + ) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PDSP_RENDER_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP %p Release Hardware", Device); + + status = STATUS_SUCCESS; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtDeviceSelfManagedIoInit( + _In_ WDFDEVICE Device + ) +/*++ + +Routine Description: + + In this callback, the driver does one-time init of self-managed I/O data. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PDSP_RENDER_DEVICE_CONTEXT devCtx; + + PAGED_CODE(); + + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + return STATUS_SUCCESS; +} + +#pragma code_seg() +VOID +DspR_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice + ) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + WDFDEVICE device; + PDSP_RENDER_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetRenderDeviceContext(device); + ASSERT(devCtx != NULL); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Device Cleanup %p", WdfDevice); +} + +#pragma code_seg() +VOID +DspR_EvtCircuitContextCleanup( + _In_ WDFOBJECT Circuit + ) +/*++ + +Routine Description: + + In this callback, it cleans up circuit context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + PDSP_CIRCUIT_CONTEXT circuitCtx; + + circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx != NULL); + + if (circuitCtx->peakMeter) + { + CSimPeakMeter* peakMeter = (CSimPeakMeter *)circuitCtx->peakMeter; + delete peakMeter; + circuitCtx->peakMeter = NULL; + } + + // clean up the path context information in case it wasn't cleaned up + // by pin disconnection. + circuitCtx->SpecialStreamAvailablePaths = 0; + + for(ULONG i = (UINT) SpecialStreamTypeUltrasoundRender; i < (UINT) SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors[i]); + circuitCtx->SpecialStreamPathDescriptors[i] = nullptr; + } + } + + for (ULONG i = (UINT)SpecialStreamTypeUltrasoundRender; i < (UINT)SpecialStreamType_Count; i++) + { + if (circuitCtx->SpecialStreamPathDescriptors2[i]) + { + ExFreePool(circuitCtx->SpecialStreamPathDescriptors2[i]); + circuitCtx->SpecialStreamPathDescriptors2[i] = nullptr; + } + } + + if (circuitCtx->SpecialStreamTargetCircuit) + { + circuitCtx->SpecialStreamTargetCircuit = nullptr; + } + + if (circuitCtx->ConnectedFunctionInformation) + { + ExFreePool(circuitCtx->ConnectedFunctionInformation); + circuitCtx->ConnectedFunctionInformation = nullptr; + } + + if (circuitCtx->AggregatedPathDescriptors) + { + ExFreePool(circuitCtx->AggregatedPathDescriptors); + circuitCtx->AggregatedPathDescriptors = nullptr; + } + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Circuit Cleanup %p", Circuit); +} + +#pragma code_seg() +VOID +DspR_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin + ) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + DSP_PIN_CONTEXT *pinCtx; + pinCtx = GetDspPinContext(WdfPin); + + if (pinCtx->TargetCircuit) + { + pinCtx->TargetCircuit = NULL; + pinCtx->TargetPinId = (ULONG)(-1); + } +} + +#pragma code_seg() +VOID +DspR_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + CircuitRequestPreprocess(Object, DriverContext, Request); +} + +PAGED_CODE_SEG +VOID +DspR_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +DspR_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Init the idle policy structure. + // + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = 10000; // 10-sec + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceAssignS0IdleSettings(Device, &idleSettings)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS DspR_EvtAcxFactoryCircuitCreateCircuitDevice( + _In_ WDFDEVICE Parent, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _Out_ WDFDEVICE * Device +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_OBJECT_ATTRIBUTES attributes; + + UNREFERENCED_PARAMETER(Factory); + + *Device = NULL; + + // Allocate a generic buffer to hold a PnP ID of this device. + // MAX_DEVICE_ID_LEN is the count of wchar in the device ID name. + C_ASSERT(NTSTRSAFE_UNICODE_STRING_MAX_CCH >= MAX_DEVICE_ID_LEN); + C_ASSERT(USHORT_MAX >= MAX_DEVICE_ID_LEN * sizeof(WCHAR)); + WCHAR *wstrBuffer = NULL; + const USHORT wstrBufferCch = MAX_DEVICE_ID_LEN; + wstrBuffer = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) WCHAR[wstrBufferCch]; + RETURN_NTSTATUS_IF_TRUE(NULL == wstrBuffer, STATUS_INSUFFICIENT_RESOURCES); + auto wstrBuffer_free = scope_exit([&wstrBuffer](){ + delete [] wstrBuffer; + }); + + RtlZeroMemory(wstrBuffer, sizeof(WCHAR) * wstrBufferCch); + + // + // Create a child audio device for this circuit. + // + PWDFDEVICE_INIT devInit = NULL; + devInit = WdfPdoInitAllocate(Parent); + RETURN_NTSTATUS_IF_TRUE(NULL == devInit, STATUS_INSUFFICIENT_RESOURCES); + auto devInit_free = scope_exit([&devInit]() { + WdfDeviceInitFree(devInit); + }); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + + // + // Create the PnP Device ID. + // + // Retrieve the unique id of this composite. This logic uses this unique id to + // make the device id unique. Using a deterministic value for the pnp device id, guarantees + // that the KS properties associated with this audio device interface stay the same across + // reboots, even when the circuit factory is used in several ACX composites. + // + { + GUID uniqueId = { 0 }; + UNICODE_STRING uniqueIdStr = { 0 }; + UNICODE_STRING pnpDeviceId = { 0 }; + ACX_OBJECTBAG_CONFIG objBagCfg; + + DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID); + + ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg); + objBagCfg.Handle = CircuitConfig->CompositeProperties; + objBagCfg.Flags |= AcxObjectBagConfigOpenWithHandle; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + ACXOBJECTBAG objBag = NULL; + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagOpen(&attributes, &objBagCfg, &objBag)); + auto objBag_free = scope_exit([&objBag]() { + WdfObjectDelete(objBag); + }); + + RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveGuid(objBag, &UniqueID, &uniqueId)); + + RETURN_NTSTATUS_IF_FAILED(RtlStringFromGUID(uniqueId, &uniqueIdStr)); + + // Init the deviceId unicode string. + pnpDeviceId.Buffer = wstrBuffer; + pnpDeviceId.Length = 0; + pnpDeviceId.MaximumLength = (USHORT)(sizeof(WCHAR) * wstrBufferCch); + + status = RtlUnicodeStringPrintf(&pnpDeviceId, RENDER_DEVICE_ID_STR, &uniqueIdStr); + + RtlFreeUnicodeString(&uniqueIdStr); + + RETURN_NTSTATUS_IF_FAILED(status); + + // This is the device ID and the first H/W ID. + // This ID is used to create a unique audio device interface. + // Note that this ID is NOT the match with this driver's INF. + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(devInit, &pnpDeviceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &pnpDeviceId)); + } + + // This H/W ID is the match with this driver's INF. + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &RenderHardwareId)); + + /* + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddCompatibleID(devInit, &RenderCompatibleId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(devInit, &RenderInstanceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignContainerID(devInit, &RenderContainerId)); + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(devInit, + &RenderDeviceLocation, + &RenderDeviceLocation, + 0x409)); + */ + + WdfPdoInitSetDefaultLocale(devInit, 0x409); + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + devInitCfg.Flags |= AcxDeviceInitConfigRawDevice; + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(devInit, &devInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = DspR_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = DspR_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = DspR_EvtDeviceSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(devInit, &pnpPowerCallbacks); + + // + // Specify a context for this render device. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_RENDER_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = DspR_EvtDeviceContextCleanup; + attributes.ExecutionLevel = WdfExecutionLevelPassive; + + WDFDEVICE device = NULL; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&devInit, &attributes, &device)); + + devInit_free.release(); + + // + // Init render's device context. + // + PDSP_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(device); + ASSERT(devCtx != NULL); + + // + // Set device capabilities. + // + { + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + + pnpCaps.SurpriseRemovalOK = WdfTrue; + pnpCaps.UniqueID = WdfFalse; + + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + } + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Parent %p Create Circuit Device %p", Parent, device); + + *Device = device; + + return status; +} + + +// {3CE41646-9BF2-4A9E-B851-D711CAE9AEA8} +DEFINE_GUID(SDCAVADPropsetId, + 0x3ce41646, 0x9bf2, 0x4a9e, 0xb8, 0x51, 0xd7, 0x11, 0xca, 0xe9, 0xae, 0xa8); + +typedef enum { + SDCAVAD_PROPERTY_TEST1, + SDCAVAD_PROPERTY_TEST2, + SDCAVAD_PROPERTY_TEST3, + SDCAVAD_PROPERTY_TEST4, + SDCAVAD_PROPERTY_TEST5, + SDCAVAD_PROPERTY_TEST6, +} SDCAVAD_Properties; + + +#pragma code_seg("PAGE") +NTSTATUS +DspR_EvtProcessCommand0( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PDSP_AUDIOMODULE0_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetDspAudioModule0Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule0_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule0_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule0_ParameterInfo[AudioModuleParameter2]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = nullptr; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +NTSTATUS +DspR_EvtProcessCommand1( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PDSP_AUDIOMODULE1_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetDspAudioModule1Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule1_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter2]; + break; + case AudioModuleParameter3: + currentValue = &audioModuleCtx->Parameter3; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter3]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = nullptr; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +NTSTATUS +DspR_EvtProcessCommand2( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PDSP_AUDIOMODULE2_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetDspAudioModule2Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule2_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule2_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule2_ParameterInfo[AudioModuleParameter2]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = nullptr; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +NTSTATUS +DspR_CreateCircuitModules( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit + ) +/*++ + +Routine Description: + + This routine creates all of the audio module elements and adds them to the circuit + +Return Value: + + NT status value + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + ACX_AUDIOMODULE_CALLBACKS audioModuleCallbacks; + ACX_AUDIOMODULE_CONFIG audioModuleCfg; + ACXAUDIOMODULE audioModuleElement; + PDSP_AUDIOMODULE0_CONTEXT audioModule0Ctx; + PDSP_AUDIOMODULE1_CONTEXT audioModule1Ctx; + PDSP_AUDIOMODULE2_CONTEXT audioModule2Ctx; + ACX_PNPEVENT_CONFIG audioModuleEventCfg; + ACXPNPEVENT audioModuleEvent; + + PAGED_CODE(); + + // Now add audio modules to the circuit + // module 0 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand0; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule0Id; + audioModuleCfg.Descriptor.ClassId = AudioModule0Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(0,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE0_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE0_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE0DESCRIPTION, + wcslen(AUDIOMODULE0DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE0_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule0Ctx = GetDspAudioModule0Context(audioModuleElement); + ASSERT(audioModule0Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule0Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 1 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand1; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule1Id; + audioModuleCfg.Descriptor.ClassId = AudioModule1Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(0,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE1_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE1_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE1DESCRIPTION, + wcslen(AUDIOMODULE1DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE1_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule1Ctx = GetDspAudioModule1Context(audioModuleElement); + ASSERT(audioModule1Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule1Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 2 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand2; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule2Id; + audioModuleCfg.Descriptor.ClassId = AudioModule2Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE2_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE2_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE2DESCRIPTION, + wcslen(AUDIOMODULE2DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE2_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule2Ctx = GetDspAudioModule2Context(audioModuleElement); + ASSERT(audioModule2Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule2Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_AddOffloadFormats( + _In_ ACXPIN Pin +) +{ + PAGED_CODE(); + + ACXCIRCUIT circuit = AcxPinGetCircuit(Pin); + WDFDEVICE device = AcxCircuitGetWdfDevice(circuit); + // PCM:44100 channel:2 24in32 + ACXDATAFORMAT formatPcm44100c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2_24in32, circuit, device, &formatPcm44100c2_24in32)); + + // PCM:48000 channel:2 24in32 + ACXDATAFORMAT formatPcm48000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2_24in32, circuit, device, &formatPcm48000c2_24in32)); + + // PCM:96000 channel:2 24in32 + ACXDATAFORMAT formatPcm96000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm96000c2_24in32, circuit, device, &formatPcm96000c2_24in32)); + + // PCM:192000 channel:2 24in32 + ACXDATAFORMAT formatPcm192000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm192000c2_24in32, circuit, device, &formatPcm192000c2_24in32)); + + // PCM:44100 channel:2 16 + ACXDATAFORMAT formatPcm44100c2; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2, circuit, device, &formatPcm44100c2)); + + // PCM:48000 channel:2 16 + ACXDATAFORMAT formatPcm48000c2; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2, circuit, device, &formatPcm48000c2)); + + // PCM:96000 channel:2 16 + ACXDATAFORMAT formatPcm96000c2; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm96000c2, circuit, device, &formatPcm96000c2)); + + // PCM:192000 channel:2 16 + ACXDATAFORMAT formatPcm192000c2; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm192000c2, circuit, device, &formatPcm192000c2)); + + // + // Add our supported formats to the raw mode for the circuit + // + ACXDATAFORMATLIST formatList = AcxPinGetRawDataFormatList(Pin); + RETURN_NTSTATUS_IF_TRUE(formatList == NULL, STATUS_INSUFFICIENT_RESOURCES); + + // + // For Offload scenarios, Windows will use 16 bit per sample offload only + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm96000c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2)); + + // Include the formats supported by the host pin as well. + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm96000c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + // + // Set up supported Default Mode formats + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = circuit; + + ACX_DATAFORMAT_LIST_CONFIG dflCfg; + ACX_DATAFORMAT_LIST_CONFIG_INIT(&dflCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListCreate(device, &attributes, &dflCfg, &formatList)); + + // + // For Offload scenarios, Windows will use 16 bit per sample offload only + // + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm96000c2)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2)); + + // Include the formats supported by the host pin as well. + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm96000c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxPinAssignModeDataFormatList(Pin, &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, formatList)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxFactoryCircuitCreateCircuit( + _In_ WDFDEVICE Parent, + _In_ WDFDEVICE Device, + _In_ ACXFACTORYCIRCUIT Factory, + _In_ PACX_FACTORY_CIRCUIT_ADD_CIRCUIT CircuitConfig, + _In_ PACXCIRCUIT_INIT CircuitInit, + _In_ ULONG DataPortNumber, + _In_opt_ PSDCA_PATH_DESCRIPTORS2 PathDescriptors +) +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Parent); + UNREFERENCED_PARAMETER(Factory); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVDspLog); + + DECLARE_CONST_UNICODE_STRING(circuitName, L"Speaker0"); + + WDF_OBJECT_ATTRIBUTES attributes; + + // + // Init output value. + // + ASSERT(Device); + + DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId); + ULONG endpointId = 0; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + RETURN_NTSTATUS_IF_FAILED(RetrieveProperties(CircuitConfig, &endpointId)); + + /////////////////////////////////////////////////////////// + // + // Create a circuit. + // + + ACXCIRCUIT circuit; + RETURN_NTSTATUS_IF_FAILED(CreateRenderCircuit(CircuitInit, circuitName, Device, &circuit)); + AcpiReader * acpiReader = GetAcpiReaderDeviceContext(Parent); + + RETURN_NTSTATUS_IF_FAILED(DetermineSpecialStreamDetailsFromVendorProperties(circuit, acpiReader, CircuitConfig->CircuitProperties)); + + ASSERT(circuit != NULL); + DSP_CIRCUIT_CONTEXT *circuitCtx; + circuitCtx = GetDspCircuitContext(circuit); + ASSERT(circuitCtx); + + circuitCtx->EndpointId = endpointId; + circuitCtx->DataPortNumber = DataPortNumber; + circuitCtx->IsRenderCircuit = TRUE; + + // + // Sim Peakmeter + // + circuitCtx->peakMeter = (PVOID)new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CSimPeakMeter(); + RETURN_NTSTATUS_IF_TRUE(NULL == circuitCtx->peakMeter, STATUS_INSUFFICIENT_RESOURCES); + + // + // Post circuit creation initialization. + // + + /////////////////////////////////////////////////////////// + // + // Allocate the formats this circuit supports. + // + // PCM:44100 channel:2 24in32 + ACXDATAFORMAT formatPcm44100c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm44100c2_24in32, circuit, Device, &formatPcm44100c2_24in32)); + + // PCM:48000 channel:2 24in32 + ACXDATAFORMAT formatPcm48000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm48000c2_24in32, circuit, Device, &formatPcm48000c2_24in32)); + + // PCM:96000 channel:2 24in32 + ACXDATAFORMAT formatPcm96000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm96000c2_24in32, circuit, Device, &formatPcm96000c2_24in32)); + + // PCM:192000 channel:2 24in32 + ACXDATAFORMAT formatPcm192000c2_24in32; + RETURN_NTSTATUS_IF_FAILED(AllocateFormat(Pcm192000c2_24in32, circuit, Device, &formatPcm192000c2_24in32)); + + /////////////////////////////////////////////////////////// + // + // Create Pins + // + ACXPIN pins[DspPinType_Count]; + + // + // Create host render pin. + // + + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = DspR_EvtAcxPinSetDataFormat; + + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSink, + circuit, + AcxPinCommunicationSink, + &KSCATEGORY_AUDIO, + &pinCallbacks, + DSPR_MAX_INPUT_HOST_STREAMS, + false, + &pins[DspPinTypeHost])); + ASSERT(pins[DspPinTypeHost] != NULL); + + PDSP_PIN_CONTEXT pinCtx; + pinCtx = GetDspPinContext(pins[DspPinTypeHost]); + ASSERT(pinCtx); + pinCtx->PinType = DspPinTypeHost; + + // + // A DSP driver could add the formats it supports here, or it could wait until + // the downstream pin is connected and discover the supported formats to use + // formats supported by the SdcaClass driver for this endpoint based on the + // DisCo data for the endpoint (e.g. supported data port widths, supported clock + // sample rates, etc.) + // + ACXDATAFORMATLIST formatList; + formatList = AcxPinGetRawDataFormatList(pins[DspPinTypeHost]); + RETURN_NTSTATUS_IF_TRUE(formatList == NULL, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + // + // Set up supported Default Mode formats + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = circuit; + ACX_DATAFORMAT_LIST_CONFIG dflCfg; + ACX_DATAFORMAT_LIST_CONFIG_INIT(&dflCfg); + AcxDataFormatListCreate(Device, &attributes, &dflCfg, &formatList); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxPinAssignModeDataFormatList(pins[DspPinTypeHost], &AUDIO_SIGNALPROCESSINGMODE_DEFAULT, formatList)); + + /////////////////////////////////////////////////////////// + // + // Create Offload Render Pin. + // + + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = DspR_EvtAcxPinSetDataFormat; + + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSink, + circuit, + AcxPinCommunicationSink, + &KSCATEGORY_AUDIO, + &pinCallbacks, + DSPR_MAX_INPUT_OFFLOAD_STREAMS, + false, + &pins[DspPinTypeOffload])); + ASSERT(pins[DspPinTypeOffload] != NULL); + + pinCtx = GetDspPinContext(pins[DspPinTypeOffload]); + ASSERT(pinCtx); + pinCtx->PinType = DspPinTypeOffload; + + RETURN_NTSTATUS_IF_FAILED(DspR_AddOffloadFormats(pins[DspPinTypeOffload])); + + /////////////////////////////////////////////////////////// + // + // Create loopback Pin. + // + + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = DspR_EvtAcxPinSetDataFormat; + + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSource, + circuit, + AcxPinCommunicationSink, + &KSNODETYPE_AUDIO_LOOPBACK, + &pinCallbacks, + DSPR_MAX_OUTPUT_LOOPBACK_STREAMS, + false, + &pins[DspPinTypeLoopback])); + ASSERT(pins[DspPinTypeLoopback] != NULL); + + pinCtx = GetDspPinContext(pins[DspPinTypeLoopback]); + ASSERT(pinCtx); + pinCtx->PinType = DspPinTypeLoopback; + + // + // Add our supported formats to the raw mode for the circuit + // + formatList = AcxPinGetRawDataFormatList(pins[DspPinTypeLoopback]); + RETURN_NTSTATUS_IF_TRUE(formatList == NULL, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + // + // Create Audio Engine + // + ACXAUDIOENGINE audioEngineElement; + RETURN_NTSTATUS_IF_FAILED(CreateAudioEngine(circuit, pins, &audioEngineElement)); + circuitCtx->AudioEngineElement = audioEngineElement; + + PDSP_ENGINE_CONTEXT audioEngineCtx; + audioEngineCtx = GetDspEngineContext(audioEngineElement); + + // + // Add our supported formats to the audio engine device format list + // + formatList = AcxAudioEngineGetDeviceFormatList(audioEngineElement); + RETURN_NTSTATUS_IF_TRUE(formatList == NULL, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + // Create a new format to use for Engine Mix format + AllocateFormat(Pcm48000c2_24in32, circuit, Device, &formatPcm48000c2_24in32); + audioEngineCtx->MixFormat = formatPcm48000c2_24in32; + + // Set the global efects as disabled + audioEngineCtx->GFxEnabled = FALSE; + + // + // Add AudioEngine to the circuit + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, (ACXELEMENT*)&audioEngineElement, 1)); + + // + // Create and add the audio modules + // + RETURN_NTSTATUS_IF_FAILED(DspR_CreateCircuitModules(Device, circuit)); + + /////////////////////////////////////////////////////////// + // + // Create bridge pin. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinConnected = DspR_EvtPinConnected; + pinCallbacks.EvtAcxPinDisconnected = DspR_EvtPinDisconnected; + + RETURN_NTSTATUS_IF_FAILED(CreatePin(AcxPinTypeSource, + circuit, + AcxPinCommunicationNone, + &KSCATEGORY_AUDIO, + &pinCallbacks, + 0, + false, + &pins[DspPinTypeBridge])); + ASSERT(pins[DspPinTypeBridge] != NULL); + + pinCtx = GetDspPinContext(pins[DspPinTypeBridge]); + ASSERT(pinCtx); + pinCtx->PinType = DspPinTypeBridge; + + // + // Add our supported formats to the raw mode for the bridge pin. + // This is required for ACX to retrieve Device format + // + formatList = AcxPinGetRawDataFormatList(pins[DspPinTypeBridge]); + RETURN_NTSTATUS_IF_TRUE(formatList == NULL, STATUS_INSUFFICIENT_RESOURCES); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32)); + + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32)); + RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm192000c2_24in32)); + + if (PathDescriptors != nullptr && PathDescriptors->Size > 0) + { + circuitCtx->AggregatedPathDescriptors = (PSDCA_PATH_DESCRIPTORS2)ExAllocatePool2(POOL_FLAG_NON_PAGED, PathDescriptors->Size, DRIVER_TAG); + if (circuitCtx->AggregatedPathDescriptors == nullptr) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlCopyMemory(circuitCtx->AggregatedPathDescriptors, PathDescriptors, PathDescriptors->Size); + } + + // + // Add a stream BRIDGE. + // + + ACX_STREAM_BRIDGE_CONFIG streamCfg; + ACX_STREAM_BRIDGE_CONFIG_INIT(&streamCfg); + + RETURN_NTSTATUS_IF_FAILED(CreateStreamBridge(streamCfg, circuit, pins[DspPinTypeBridge], pinCtx, DataPortNumber, endpointId, PathDescriptors, true)); + + // + // Add bridge pin + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, pins, DspPinType_Count)); + + RETURN_NTSTATUS_IF_FAILED(ConnectRenderCircuitElements(audioEngineElement, circuit)); + + // + // Store the circuit handle in the render device context. + // + PDSP_RENDER_DEVICE_CONTEXT renderDevCtx = NULL; + renderDevCtx = GetRenderDeviceContext(Device); + ASSERT(renderDevCtx); + renderDevCtx->Circuit = circuit; + renderDevCtx->FirstTimePrepareHardware = TRUE; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCA VDSP Circuit Device %p Create Circuit %p", Device, circuit); + + return status; +} + +#pragma code_seg() +_Use_decl_annotations_ +NTSTATUS +DspR_EvtCircuitPowerUp ( + WDFDEVICE, + ACXCIRCUIT, + WDF_POWER_DEVICE_STATE + ) +{ + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +NTSTATUS +DspR_EvtCircuitPowerDown ( + WDFDEVICE Device, + ACXCIRCUIT Circuit, + WDF_POWER_DEVICE_STATE TargetState + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtCircuitCompositeCircuitInitialize( + WDFDEVICE Device, + ACXCIRCUIT Circuit, + ACXOBJECTBAG CircuitProperties + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(CircuitProperties); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtCircuitCompositeInitialize( + WDFDEVICE Device, + ACXCIRCUIT Circuit, + ACXOBJECTBAG CompositeProperties + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(CompositeProperties); + + return status; +} + +#pragma code_seg("PAGE") +NTSTATUS +DspR_CreateStreamModules( + _In_ WDFDEVICE Device, + _In_ ACXSTREAM Stream + ) +/*++ + +Routine Description: + + This routine creates all of the audio module elements and adds them to the stream + +Return Value: + + NT status value + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + ACX_AUDIOMODULE_CALLBACKS audioModuleCallbacks; + ACX_AUDIOMODULE_CONFIG audioModuleCfg; + ACXAUDIOMODULE audioModuleElement; + PDSP_AUDIOMODULE0_CONTEXT audioModule0Ctx; + PDSP_AUDIOMODULE1_CONTEXT audioModule1Ctx; + PDSP_AUDIOMODULE2_CONTEXT audioModule2Ctx; + ACX_PNPEVENT_CONFIG audioModuleEventCfg; + ACXPNPEVENT audioModuleEvent; + + PAGED_CODE(); + + // Now add audio modules to the stream + // module 0 + // for simplicity of the example, we implement the same modules on the stream as is + // on the circuit + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand0; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule0Id; + audioModuleCfg.Descriptor.ClassId = AudioModule0Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE0_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE0_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE0DESCRIPTION, + wcslen(AUDIOMODULE0DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE0_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule0Ctx = GetDspAudioModule0Context(audioModuleElement); + ASSERT(audioModule0Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule0Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 1 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand1; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule1Id; + audioModuleCfg.Descriptor.ClassId = AudioModule1Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE1_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE1_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE1DESCRIPTION, + wcslen(AUDIOMODULE1DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE1_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule1Ctx = GetDspAudioModule1Context(audioModuleElement); + ASSERT(audioModule1Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule1Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 2 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = DspR_EvtProcessCommand2; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule2Id; + audioModuleCfg.Descriptor.ClassId = AudioModule2Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(2,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE2_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE2_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE2DESCRIPTION, + wcslen(AUDIOMODULE2DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_AUDIOMODULE2_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule2Ctx = GetDspAudioModule2Context(audioModuleElement); + ASSERT(audioModule2Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule2Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT DataFormat, + _In_ const GUID* SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + DrvLogEnter(g_SDCAVDspLog); + + NTSTATUS status = STATUS_SUCCESS; + + PDSP_PIN_CONTEXT pinCtx = GetDspPinContext(Pin); + ASSERT(pinCtx); + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + { + ASSERT(pinCtx->CurrentStreamsCount != (ULONG)-1); + RETURN_NTSTATUS_IF_TRUE_MSG( + pinCtx->CurrentStreamsCount >= pinCtx->MaxStreams, + STATUS_INSUFFICIENT_RESOURCES, + L"ACXCIRCUIT %p ACXPIN %p cannot create another ACXSTREAM, max count is %d, %!STATUS!", + Circuit, Pin, pinCtx->MaxStreams, status); + } +#endif + + // Check incorrect pin instantiation. + RETURN_NTSTATUS_IF_TRUE_MSG(NULL == pinCtx, STATUS_INVALID_PARAMETER, L"Incorrect pin is being instantiated"); + RETURN_NTSTATUS_IF_TRUE_MSG( + NULL == pinCtx || + (pinCtx->PinType != DspPinTypeHost && + pinCtx->PinType != DspPinTypeOffload && + pinCtx->PinType != DspPinTypeLoopback), + STATUS_INVALID_PARAMETER, L"Incorrect pin is being instantiated"); + + // + // TEST sending KS Property to connected circuits + // + ULONG testValue = 7; + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST1, + AcxPropertyVerbSet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST1 SET :%!STATUS!, Value = %d", status, testValue); + + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST2, + AcxPropertyVerbGet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST2 GET :%!STATUS!, Value = %d", status, testValue); + + testValue = 8; + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST3, + AcxPropertyVerbSet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST3 SET :%!STATUS!, Value = %d", status, testValue); + + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST4, + AcxPropertyVerbGet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST4 GET :%!STATUS!, Value = %d", status, testValue); + + testValue = 9; + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST5, + AcxPropertyVerbSet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST5 SET :%!STATUS!, Value = %d", status, testValue); + + status = Dsp_SendTestPropertyTo( + Device, + Circuit, + SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST6, + AcxPropertyVerbGet, + nullptr, 0, + &testValue, sizeof(ULONG), + nullptr); + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"SDCAVAD_PROPERTY_TEST6 GET :%!STATUS!, Value = %d", status, testValue); + + status = STATUS_SUCCESS; + + if (pinCtx->PinType != DspPinTypeOffload) + { + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + DspR_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + } + + // + // Request a Vendor-Specific property from the Controller + // + Dsp_SendVendorSpecificProperties( + Device, + Circuit, + TRUE); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = Dsp_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = Dsp_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = Dsp_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = Dsp_EvtStreamPause; + streamCallbacks.EvtAcxStreamAssignDrmContentId = Dsp_EvtStreamAssignDrmContentId; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Init RT streaming callbacks. + // + ACX_RT_STREAM_CALLBACKS rtCallbacks; + ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks); + rtCallbacks.EvtAcxStreamGetHwLatency = Dsp_EvtStreamGetHwLatency; + rtCallbacks.EvtAcxStreamAllocateRtPackets = Dsp_EvtStreamAllocateRtPackets; + rtCallbacks.EvtAcxStreamFreeRtPackets = Dsp_EvtStreamFreeRtPackets; + rtCallbacks.EvtAcxStreamSetRenderPacket = DspR_EvtStreamSetRenderPacket; + rtCallbacks.EvtAcxStreamGetCurrentPacket = Dsp_EvtStreamGetCurrentPacket; + rtCallbacks.EvtAcxStreamGetPresentationPosition = Dsp_EvtStreamGetPresentationPosition; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRtStreamCallbacks(StreamInit, &rtCallbacks)); + + // + // Buffer notifications are supported. + // + AcxStreamInitSetAcxRtStreamSupportsNotifications(StreamInit); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + ACXSTREAM stream; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_STREAM_CONTEXT); + attributes.EvtDestroyCallback = Dsp_EvtStreamContextDestroy; + attributes.EvtCleanupCallback = Dsp_EvtStreamContextCleanup; + + + RETURN_NTSTATUS_IF_FAILED(AcxRtStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + PDSP_CIRCUIT_CONTEXT circuitCtx = GetDspCircuitContext(Circuit); + ASSERT(circuitCtx); + + CStreamEngine* streamEngine = NULL; + if (pinCtx->PinType == DspPinTypeOffload) + { + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) COffloadStreamEngine(stream, DataFormat, (CSimPeakMeter *)circuitCtx->peakMeter); + } + else + { + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CRenderStreamEngine(stream, DataFormat, (CSimPeakMeter *)circuitCtx->peakMeter); + } + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES); + + DSP_STREAM_CONTEXT* streamCtx; + streamCtx = GetDspStreamContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)streamEngine; + streamEngine = NULL; + streamCtx->PinType = pinCtx->PinType; + + if (DspPinTypeLoopback == pinCtx->PinType && + circuitCtx->SpecialStreamAvailablePaths & SdcaPathReferenceStream) + { + WdfObjectReferenceWithTag(circuitCtx->SpecialStreamTargetCircuit, (PVOID)DRIVER_TAG); + streamCtx->SpecialStreamTargetCircuit = circuitCtx->SpecialStreamTargetCircuit; + } + + if ((DspPinTypeHost == pinCtx->PinType || DspPinTypeOffload == pinCtx->PinType) && + circuitCtx->SpecialStreamAvailablePaths & SdcaPathIvSense) + { + WdfObjectReferenceWithTag(circuitCtx->SpecialStreamTargetCircuit, (PVOID)DRIVER_TAG); + streamCtx->SpecialStreamTargetCircuit = circuitCtx->SpecialStreamTargetCircuit; + } + + // + // Post stream creation initialization. + // + + if (circuitCtx->AudioEngineElement != nullptr) + { + // + // The circuit has an Audio Engine element, so all streams created for the circuit + // also require an Audio Engine element to allow the OS to + // * Adjust per-stream volume and mute + // * Monitor per-stream peakmeter values + // * Retrieve stream position + // * Set stream effects state + // + + // + // Volume Element + // + ACX_VOLUME_CALLBACKS volumeCallbacks; + ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks); + volumeCallbacks.EvtAcxRampedVolumeAssignLevel = DspR_EvtRampedVolumeAssignLevel; + volumeCallbacks.EvtAcxVolumeRetrieveLevel = DspR_EvtVolumeRetrieveLevel; + + // Create Volume element for the audio engine to use + ACX_VOLUME_CONFIG volumeCfg; + ACX_VOLUME_CONFIG_INIT(&volumeCfg); + volumeCfg.ChannelsCount = MAX_CHANNELS; + volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM; + volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM; + volumeCfg.SteppingDelta = VOLUME_STEPPING; + volumeCfg.Name = &KSAUDFNAME_VOLUME_CONTROL; + volumeCfg.Callbacks = &volumeCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_VOLUME_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXVOLUME volumeElement; + RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(stream, &attributes, &volumeCfg, &volumeElement)); + + // + // Mute Element + // + ACX_MUTE_CALLBACKS muteCallbacks; + ACX_MUTE_CALLBACKS_INIT(&muteCallbacks); + muteCallbacks.EvtAcxMuteAssignState = DspR_EvtMuteAssignState; + muteCallbacks.EvtAcxMuteRetrieveState = DspR_EvtMuteRetrieveState; + + ACX_MUTE_CONFIG muteCfg; + ACX_MUTE_CONFIG_INIT(&muteCfg); + muteCfg.ChannelsCount = MAX_CHANNELS; + muteCfg.Name = &KSAUDFNAME_WAVE_MUTE; + muteCfg.Callbacks = &muteCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_MUTE_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXMUTE muteElement; + RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(stream, &attributes, &muteCfg, &muteElement)); + + // + // Peakmeter Element + // + ACX_PEAKMETER_CALLBACKS peakmeterCallbacks; + ACX_PEAKMETER_CALLBACKS_INIT(&peakmeterCallbacks); + peakmeterCallbacks.EvtAcxPeakMeterRetrieveLevel = DspR_EvtPeakMeterRetrieveLevelCallback; + + ACX_PEAKMETER_CONFIG peakmeterCfg; + ACX_PEAKMETER_CONFIG_INIT(&peakmeterCfg); + peakmeterCfg.ChannelsCount = MAX_CHANNELS; + peakmeterCfg.Minimum = PEAKMETER_MINIMUM; + peakmeterCfg.Maximum = PEAKMETER_MAXIMUM; + peakmeterCfg.SteppingDelta = PEAKMETER_STEPPING_DELTA; + peakmeterCfg.Callbacks = &peakmeterCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_PEAKMETER_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXPEAKMETER peakmeterElement; + RETURN_NTSTATUS_IF_FAILED(AcxPeakMeterCreate(stream, &attributes, &peakmeterCfg, &peakmeterElement)); + + PDSP_PEAKMETER_ELEMENT_CONTEXT peakmeterCtx; + ASSERT(peakmeterElement != NULL); + peakmeterCtx = GetDspPeakMeterElementContext(peakmeterElement); + ASSERT(peakmeterCtx); + peakmeterCtx->peakMeter = ((CStreamEngine*)streamCtx->StreamEngine)->GetPeakMeter(); + + // + // Stream Audio Engine Node + // + ACX_STREAMAUDIOENGINE_CALLBACKS streamAudioEngineCallbacks; + // Create the AudioEngine element to control offloaded streaming. + ACX_STREAMAUDIOENGINE_CALLBACKS_INIT(&streamAudioEngineCallbacks); + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineAssignEffectsState = DspR_EvtAcxStreamAudioEngineAssignEffectsState; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineRetrieveEffectsState = DspR_EvtAcxStreamAudioEngineRetrieveEffectsState; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineRetrievePresentationPosition = DspR_EvtAcxStreamAudioEngineRetrievePresentationPosition; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineAssignCurrentWritePosition = DspR_EvtAcxStreamAudioEngineAssignCurrentWritePosition; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineRetrieveLinearBufferPosition = DspR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineAssignLastBufferPosition = DspR_EvtAcxStreamAudioEngineAssignLastBufferPosition; + streamAudioEngineCallbacks.EvtAcxStreamAudioEngineAssignLoopbackProtection = DspR_EvtAcxStreamAudioEngineAssignLoopbackProtection; + + ACX_STREAMAUDIOENGINE_CONFIG audioEngineCfg; + ACX_STREAMAUDIOENGINE_CONFIG_INIT(&audioEngineCfg); + audioEngineCfg.VolumeElement = volumeElement; + audioEngineCfg.MuteElement = muteElement; + audioEngineCfg.PeakMeterElement = peakmeterElement; + audioEngineCfg.Callbacks = &streamAudioEngineCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_STREAMAUDIOENGINE_CONTEXT); + attributes.ParentObject = stream; + + ACXELEMENT streamAudioEngine; + RETURN_NTSTATUS_IF_FAILED(AcxStreamAudioEngineCreate(stream, circuitCtx->AudioEngineElement, &attributes, &audioEngineCfg, (ACXSTREAMAUDIOENGINE*)&streamAudioEngine)); + + // Set local effects as disabled + PDSP_STREAMAUDIOENGINE_CONTEXT pStreamAudioEngineCtx; + pStreamAudioEngineCtx = GetDspStreamAudioEngineContext(streamAudioEngine); + pStreamAudioEngineCtx->LFxEnabled = FALSE; + + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, &streamAudioEngine, 1)); + + // Add our stream audio modules + RETURN_NTSTATUS_IF_FAILED(DspR_CreateStreamModules(Device, stream)); + } + else + { + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + ACXELEMENT elements[2] = { 0 }; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + DSP_ELEMENT_CONTEXT* elementCtx; + elementCtx = GetDspElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DSP_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetDspElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + // Add our stream audio modules + RETURN_NTSTATUS_IF_FAILED(DspR_CreateStreamModules(Device, stream)); + } + +// See description in private.h +#ifdef ACX_WORKAROUND_ACXPIN_01 + { + ASSERT(pinCtx->CurrentStreamsCount != (ULONG)-1); + InterlockedIncrement(PLONG(&pinCtx->CurrentStreamsCount)); + streamCtx->StreamIsCounted = TRUE; + } +#endif + + streamCtx->Pin = Pin; + WdfObjectReferenceWithTag(Pin, (PVOID)DRIVER_TAG); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +DspR_EvtStreamSetRenderPacket( + _In_ ACXSTREAM Stream, + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength + ) +{ + PDSP_STREAM_CONTEXT ctx; + CRenderStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetDspStreamContext(Stream); + + streamEngine = static_cast<CRenderStreamEngine*>(ctx->StreamEngine); + + return streamEngine->SetRenderPacket(Packet, Flags, EosPacketLength); +} + +// +//#pragma code_seg() +//NTSTATUS +//DspR_EvtAcxCircuitProcess( +// _In_ ACXCIRCUIT Circuit, +// _In_ ACXSTREAMIO Stream +// ) +//{ +// UNREFERENCED_PARAMETER(Circuit); +// UNREFERENCED_PARAMETER(Stream); +// +// return STATUS_SUCCESS; +//} +// + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/renderAudioEngine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/renderAudioEngine.cpp new file mode 100644 index 00000000..e9bb9496 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/renderAudioEngine.cpp @@ -0,0 +1,502 @@ +/*++ + + 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: + + renderaudioengine.cpp + +Abstract: + + Render Audio Engine - callbacks for Audio Engine Node + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "offloadStreamEngine.h" +#include "SimPeakMeter.h" + +#include "TestProperties.h" +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "renderaudioengine.tmh" +#endif + +// Sizes for min/max for audioengine buffers +// Buffer duration is for both ping and pong buffers combined +// so multiply it by 2 +#define MIN_AUDIOENGINE_BUFFER_DURATION_IN_MS (10 * 2) +#define MAX_AUDIOENGINE_BUFFER_DURATION_IN_MS (2000 * 2) + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxAudioEngineRetrieveBufferSizeLimits( + ACXAUDIOENGINE, + ACXDATAFORMAT DataFormat, + PULONG MinBufferBytes, + PULONG MaxBufferBytes + ) +{ + PAGED_CODE(); + + ULONG bytesPerSecond = AcxDataFormatGetAverageBytesPerSec(DataFormat); + + *MinBufferBytes = (ULONG) (MIN_AUDIOENGINE_BUFFER_DURATION_IN_MS * bytesPerSecond / 1000); + *MaxBufferBytes = (ULONG) (MAX_AUDIOENGINE_BUFFER_DURATION_IN_MS * bytesPerSecond / 1000); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxAudioEngineRetrieveEffectsState( + ACXAUDIOENGINE AudioEngine, + PULONG State +) +{ + PAGED_CODE(); + + PDSP_ENGINE_CONTEXT pAudioEngineCtx; + pAudioEngineCtx = GetDspEngineContext(AudioEngine); + + *State = pAudioEngineCtx->GFxEnabled; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxAudioEngineAssignEffectsState( + ACXAUDIOENGINE AudioEngine, + ULONG State +) +{ + PAGED_CODE(); + + PDSP_ENGINE_CONTEXT pAudioEngineCtx; + pAudioEngineCtx = GetDspEngineContext(AudioEngine); + + pAudioEngineCtx->GFxEnabled = (BOOLEAN)State; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineRetrieveEffectsState( + ACXSTREAMAUDIOENGINE StreamAudioEngine, + PULONG State +) +{ + PAGED_CODE(); + + PDSP_STREAMAUDIOENGINE_CONTEXT pStreamAudioEngineCtx; + pStreamAudioEngineCtx = GetDspStreamAudioEngineContext(StreamAudioEngine); + + *State = pStreamAudioEngineCtx->LFxEnabled; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineAssignEffectsState( + ACXSTREAMAUDIOENGINE StreamAudioEngine, + ULONG State +) +{ + PAGED_CODE(); + + PDSP_STREAMAUDIOENGINE_CONTEXT pStreamAudioEngineCtx; + pStreamAudioEngineCtx = GetDspStreamAudioEngineContext(StreamAudioEngine); + + pStreamAudioEngineCtx->LFxEnabled = (BOOLEAN)State; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxAudioEngineRetrieveEngineMixFormat( + ACXAUDIOENGINE AudioEngine, + ACXDATAFORMAT * Format + ) +{ + PDSP_ENGINE_CONTEXT audioEngineCtx; + PAGED_CODE(); + + audioEngineCtx = GetDspEngineContext(AudioEngine); + + if (!audioEngineCtx->MixFormat) + { + return STATUS_INVALID_DEVICE_STATE; + } + + *Format = audioEngineCtx->MixFormat; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxAudioEngineAssignEngineDeviceFormat( + _In_ ACXAUDIOENGINE AudioEngine, + _In_ ACXDATAFORMAT Format + ) +{ + PAGED_CODE(); + + // Get the downstream pin + ACXCIRCUIT parentCircuit = (ACXCIRCUIT)AcxElementGetContainer((ACXELEMENT)AudioEngine); + + ACXPIN downstreamPin = AcxCircuitGetPinById(parentCircuit, DspPinTypeBridge); + if (!downstreamPin) + { + RETURN_NTSTATUS(STATUS_INTERNAL_ERROR); + } + + // Start by getting the list of formats for the raw mode + ACXDATAFORMATLIST formatList; + RETURN_NTSTATUS_IF_FAILED(AcxPinRetrieveModeDataFormatList(downstreamPin, &AUDIO_SIGNALPROCESSINGMODE_RAW, &formatList)); + + // Find the format we were given in that list. + NTSTATUS status = STATUS_NO_MATCH; + + ACX_DATAFORMAT_LIST_ITERATOR formatListIter; + ACX_DATAFORMAT_LIST_ITERATOR_INIT(&formatListIter); + AcxDataFormatListBeginIteration(formatList, &formatListIter); + + ACXDATAFORMAT listFormat; + while (NT_SUCCESS(AcxDataFormatListRetrieveNextFormat(formatList, &formatListIter, &listFormat))) + { + if (AcxDataFormatIsEqual(listFormat, Format)) + { + // Assign the format as the default format. + // Note there is an existing ACX issue with default format assignment - assigning the default + // will only work if the format is already in the list (or is the first format added to the list). + AcxDataFormatListAssignDefaultDataFormat(formatList, listFormat); + + // Use the format we pulled out of our list since it will have an appropriate lifetime + PDSP_ENGINE_CONTEXT audioEngineCtx; + audioEngineCtx = GetDspEngineContext(AudioEngine); + audioEngineCtx->MixFormat = listFormat; + + status = STATUS_SUCCESS; + + break; + } + } + AcxDataFormatListEndIteration(formatList, &formatListIter); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtPeakMeterRetrieveLevelCallback( + ACXPEAKMETER PeakMeter, + ULONG Channel, + LONG * PeakMeterLevel + ) +{ + PAGED_CODE(); + + ASSERT(PeakMeter); + + if (Channel == ALL_CHANNELS_ID) + { + Channel = 0; + } + + PDSP_PEAKMETER_ELEMENT_CONTEXT peakmeterCtx = GetDspPeakMeterElementContext(PeakMeter); + ASSERT(peakmeterCtx); + CSimPeakMeter* peakMeter = (CSimPeakMeter *)peakmeterCtx->peakMeter; + *PeakMeterLevel = peakMeter->GetValue(Channel); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtMuteAssignState( + ACXMUTE Mute, + ULONG Channel, + ULONG State + ) +{ + PDSP_MUTE_ELEMENT_CONTEXT muteCtx; + ULONG i; + + PAGED_CODE(); + + muteCtx = GetDspMuteElementContext(Mute); + ASSERT(muteCtx); + + if (Channel != ALL_CHANNELS_ID) + { + muteCtx->MuteState[Channel] = State; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + muteCtx->MuteState[i] = State; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtMuteRetrieveState( + ACXMUTE Mute, + ULONG Channel, + ULONG * State + ) +{ + PDSP_MUTE_ELEMENT_CONTEXT muteCtx; + + PAGED_CODE(); + + muteCtx = GetDspMuteElementContext(Mute); + ASSERT(muteCtx); + + // use first channel for all channels setting. + if (Channel != ALL_CHANNELS_ID) + { + *State = muteCtx->MuteState[Channel]; + } + else + { + *State = muteCtx->MuteState[0]; + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtRampedVolumeAssignLevel( + ACXVOLUME Volume, + ULONG Channel, + LONG VolumeLevel, + ACX_VOLUME_CURVE_TYPE, + ULONGLONG + ) +{ + PDSP_VOLUME_ELEMENT_CONTEXT volumeCtx; + ULONG i; + + PAGED_CODE(); + + volumeCtx = GetDspVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + volumeCtx->VolumeLevel[Channel] = VolumeLevel; + } + else + { + for (i = 0; i < MAX_CHANNELS; ++i) + { + volumeCtx->VolumeLevel[i] = VolumeLevel; + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtVolumeRetrieveLevel( + ACXVOLUME Volume, + ULONG Channel, + LONG * VolumeLevel +) +{ + PDSP_VOLUME_ELEMENT_CONTEXT volumeCtx; + + PAGED_CODE(); + + volumeCtx = GetDspVolumeElementContext(Volume); + ASSERT(volumeCtx); + + if (Channel != ALL_CHANNELS_ID) + { + *VolumeLevel = volumeCtx->VolumeLevel[Channel]; + } + else + { + *VolumeLevel = volumeCtx->VolumeLevel[0]; + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineRetrievePresentationPosition( + _In_ ACXSTREAMAUDIOENGINE StreamAudioEngine, + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition +) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + ACXSTREAM stream; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + stream = AcxStreamAudioEngineGetStream(StreamAudioEngine); + if (stream) + { + ctx = GetDspStreamContext(stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + status = streamEngine->GetPresentationPosition(PositionInBlocks, QPCPosition); + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineAssignCurrentWritePosition( + _In_ ACXSTREAMAUDIOENGINE StreamAudioEngine, + _In_ ULONG Position +) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + ACXSTREAM stream; + PDSP_STREAM_CONTEXT ctx; + COffloadStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + stream = AcxStreamAudioEngineGetStream(StreamAudioEngine); + if (stream) + { + ctx = GetDspStreamContext(stream); + + if (ctx->PinType == DspPinTypeOffload) + { + streamEngine = static_cast<COffloadStreamEngine*>(ctx->StreamEngine); + + status = streamEngine->SetCurrentWritePosition(Position); + } + else + { + status = STATUS_NOT_SUPPORTED; + } + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineRetrieveLinearBufferPosition( + _In_ ACXSTREAMAUDIOENGINE StreamAudioEngine, + _Out_ PULONGLONG Position +) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + ACXSTREAM stream; + PDSP_STREAM_CONTEXT ctx; + CStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + stream = AcxStreamAudioEngineGetStream(StreamAudioEngine); + if (stream) + { + ctx = GetDspStreamContext(stream); + + streamEngine = static_cast<CStreamEngine*>(ctx->StreamEngine); + + status = streamEngine->GetLinearBufferPosition(Position); + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineAssignLastBufferPosition( + _In_ ACXSTREAMAUDIOENGINE StreamAudioEngine, + _In_ ULONG Position +) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + ACXSTREAM stream; + PDSP_STREAM_CONTEXT ctx; + COffloadStreamEngine* streamEngine = NULL; + + PAGED_CODE(); + + stream = AcxStreamAudioEngineGetStream(StreamAudioEngine); + if (stream) + { + ctx = GetDspStreamContext(stream); + + if (ctx->PinType == DspPinTypeOffload) + { + streamEngine = static_cast<COffloadStreamEngine*>(ctx->StreamEngine); + + status = streamEngine->SetLastBufferPosition(Position); + } + else + { + status = STATUS_NOT_SUPPORTED; + } + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +DspR_EvtAcxStreamAudioEngineAssignLoopbackProtection( + _In_ ACXSTREAMAUDIOENGINE, + _In_ ACX_CONSTRICTOR_OPTION +) +{ + PAGED_CODE(); + + return STATUS_SUCCESS; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/resources.rc b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/resources.rc new file mode 100644 index 00000000..a2cc093a --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/resources.rc @@ -0,0 +1,12 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "ACX v1.0 DSP Audio Driver" +#define VER_INTERNALNAME_STR "SDCAVDsp.sys" +#define VER_ORIGINALFILENAME_STR "SDCAVDsp.sys" + +#include "common.ver" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.cpp new file mode 100644 index 00000000..4d70ad09 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.cpp @@ -0,0 +1,1043 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + savedata.cpp + +Abstract: + + Implementation of ACX DSP Test Driver 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 "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.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 OFFLOAD_FILE_NAME L"OFFLOAD" +#define HOST_FILE_NAME L"HOST" + +#define MAX_WORKER_ITEM_COUNT 15 + + +PSAVEWORKER_PARAM CSaveData::m_pWorkItems = NULL; +PDEVICE_OBJECT CSaveData::m_pDeviceObject = NULL; + +//============================================================================= +// Statics +//============================================================================= +ULONG CSaveData::m_ulStreamId = 0; +ULONG CSaveData::m_ulOffloadStreamId = 0; + +//============================================================================= +// CSaveData +//============================================================================= + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::~CSaveData() +{ + PAGED_CODE(); + Cleanup(); +} // CSaveData + +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::Cleanup +( + void +) +{ + PAGED_CODE(); + + // Update the wave header in data file with real file size. + // + if(m_pFilePtr) + { + // RIFF header, whose size is the whole file size minus RIFF header. + m_FileHeader.dwFileSize = + (DWORD)m_pFilePtr->QuadPart - 2 * sizeof(DWORD); + // The data length is the size of all the audio that was written. + // It gets calculated by taking: + m_DataHeader.dwDataLength = (DWORD)m_pFilePtr->QuadPart - // the whole file size, + sizeof(m_FileHeader) - // minus the file header, + m_FileHeader.dwFormatLength - // minus the format, + sizeof(m_DataHeader); // minus the data header itself. + + if (STATUS_SUCCESS == KeWaitForSingleObject + ( + &m_FileSync, + Executive, + KernelMode, + FALSE, + NULL + )) + { + if (NT_SUCCESS(FileOpen(FALSE))) + { + FileWriteHeader(); + + FileClose(); + } + + KeReleaseMutex(&m_FileSync, FALSE); + } + + 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; + m_pFilePtr = NULL; + } + + if (m_waveFormat) + { + ExFreePoolWithTag(m_waveFormat, SAVEDATA_POOLTAG1); + m_waveFormat = NULL; + } + + if (m_fFrameUsed) + { + ExFreePoolWithTag(m_fFrameUsed, SAVEDATA_POOLTAG2); + m_fFrameUsed = NULL; + } + + 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; + } +} + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::Disable +( + _In_ BOOL fDisable +) +{ + PAGED_CODE(); + + m_fWriteDisabled = fDisable; +} // Disable + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileClose(void) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (m_FileHandle) + { + ntStatus = ZwClose(m_FileHandle); + m_FileHandle = NULL; + } + + return ntStatus; +} // FileClose + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileOpen +( + 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 + ); + } + + return ntStatus; +} // FileOpen + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::FileWrite +( + PBYTE pData, + 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 + { + ntStatus = STATUS_INVALID_HANDLE; + } + + return ntStatus; +} // FileWrite + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +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)) + { + 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)) + { + 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)) + { + m_pFilePtr->QuadPart += sizeof(m_DataHeader); + } + } + else + { + ntStatus = STATUS_INVALID_HANDLE; + } + + + return ntStatus; +} // FileWriteHeader + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDeviceObject +( + PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + m_pDeviceObject = DeviceObject; + return ntStatus; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +PDEVICE_OBJECT +CSaveData::GetDeviceObject +( + void +) +{ + PAGED_CODE(); + + return m_pDeviceObject; +} + +//============================================================================= +_Use_decl_annotations_ +#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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::Initialize +( + BOOL _bOffloaded +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + WCHAR szTemp[MAX_PATH]; + size_t cLen; + + if (_bOffloaded) + { + m_ulOffloadStreamId++; + } + else + { + m_ulStreamId++; + } + + // Allocate data file name. + // + RtlStringCchPrintfW(szTemp, MAX_PATH, L"%s_%s_%d.wav", DEFAULT_FILE_NAME, _bOffloaded ? OFFLOAD_FILE_NAME : HOST_FILE_NAME, _bOffloaded ? m_ulOffloadStreamId : 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) + { + 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); + + m_pDataBuffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + m_ulBufferSize, + SAVEDATA_POOLTAG4 + ); + if (!m_pDataBuffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + // ExAllocatePool2 zeros memory. + } + } + + // 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) + { + 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)); + RtlZeroMemory(m_fFrameUsed, m_ulFrameCount * sizeof(BOOL) + sizeof(LARGE_INTEGER)); + + // 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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::InitializeWorkItems +( + PDEVICE_OBJECT DeviceObject +) +{ + PAGED_CODE(); + + ASSERT(DeviceObject); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + 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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +SaveFrameWorkerCallback +( + PDEVICE_OBJECT pDeviceObject, + 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; + } + + 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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetDataFormat +( + PKSDATAFORMAT pDataFormat +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + 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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CSaveData::SetMaxWriteSize +( + ULONG ulMaxWriteSize +) +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG bufferSize = 0; + PBYTE buffer = NULL; + + // + // Compute new buffer size. + // + ntStatus = RtlULongMult(ulMaxWriteSize, DEFAULT_FRAME_COUNT, &bufferSize); + if (!NT_SUCCESS(ntStatus)) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // + // Alloc memory for buffer. + // + buffer = (PBYTE) + ExAllocatePool2 + ( + POOL_FLAG_NON_PAGED, + bufferSize, + SAVEDATA_POOLTAG4 + ); + if (!buffer) + { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + goto Done; + } + + // ExAllocatePool2 zeros memory. + + // + // 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 + +//============================================================================= +_Use_decl_annotations_ +PAGED_CODE_SEG +void +CSaveData::ReadData +( + PBYTE pBuffer, + ULONG ulByteCount +) +{ + UNREFERENCED_PARAMETER(pBuffer); + UNREFERENCED_PARAMETER(ulByteCount); + + PAGED_CODE(); + + // Not implemented yet. +} // ReadData + +//============================================================================= +_Use_decl_annotations_ +#pragma code_seg() +void +CSaveData::SaveFrame +( + ULONG ulFrameNo, + ULONG ulDataSize +) +{ + PSAVEWORKER_PARAM pParam = NULL; + + 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 + +//============================================================================= +void +_Use_decl_annotations_ +PAGED_CODE_SEG +CSaveData::WaitAllWorkItems +( + void +) +{ + PAGED_CODE(); + + // 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++) + { + KeWaitForSingleObject + ( + &(m_pWorkItems[i].EventDone), + Executive, + KernelMode, + FALSE, + NULL + ); + } +} // WaitAllWorkItems + +//============================================================================= +_Use_decl_annotations_ +#pragma code_seg() +void +CSaveData::WriteData +( + PBYTE pBuffer, + ULONG ulByteCount +) +{ + ASSERT(pBuffer); + + BOOL fSaveFrame = FALSE; + ULONG ulSaveFrameIndex = 0; + KIRQL oldIrql; + + // If stream writing is disabled, then exit. + // + if (m_fWriteDisabled) + { + return; + } + + 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); + } + } + + if (fSaveFrame) + { + SaveFrame(ulSaveFrameIndex, m_ulFrameSize); + } + } + else + { + KeReleaseSpinLock(&m_FrameInUseSpinLock, oldIrql ); + } + +} // WriteData + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.h new file mode 100644 index 00000000..2cc1eb47 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/savedata.h @@ -0,0 +1,257 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + savedata.h + +Abstract: + + Declaration of ACX DSP Test Driver data saving class. This class supplies services +to save data to disk. + + +--*/ + +#pragma once + +//----------------------------------------------------------------------------- +// 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. +// +__drv_maxIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +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 ULONG m_ulOffloadStreamId; + static PSAVEWORKER_PARAM m_pWorkItems; + + BOOL m_fWriteDisabled; + + BOOL m_bInitialized; + +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CSaveData(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Cleanup( + void + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + InitializeWorkItems( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + DestroyWorkItems( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + Disable( + _In_ BOOL fDisable + ); + + static + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + PSAVEWORKER_PARAM + GetNewWorkItem( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Initialize( + _In_ BOOL _bOffloaded + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDeviceObject( + _In_ PDEVICE_OBJECT DeviceObject + ); + + static + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + PDEVICE_OBJECT + GetDeviceObject( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + ReadData( + _Inout_updates_bytes_all_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetDataFormat( + _In_ PKSDATAFORMAT pDataFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetMaxWriteSize( + _In_ ULONG ulMaxWriteSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + void + WaitAllWorkItems( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + void + WriteData( + _In_reads_bytes_(ulByteCount) PBYTE pBuffer, + _In_ ULONG ulByteCount + ); + +private: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileClose( + void + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileOpen( + _In_ BOOL fOverWrite + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWrite( + _In_reads_bytes_(ulDataSize) PBYTE pData, + _In_ ULONG ulDataSize + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + FileWriteHeader( + void + ); + + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + void + SaveFrame( + _In_ ULONG ulFrameNo, + _In_ ULONG ulDataSize + ); + + friend + IO_WORKITEM_ROUTINE SaveFrameWorkerCallback; +}; +typedef CSaveData *PCSaveData; + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.cpp new file mode 100644 index 00000000..a979a129 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.cpp @@ -0,0 +1,1053 @@ +/*++ + + 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: + + StreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "streamengine.h" + +#ifndef __INTELLISENSE__ +#include "streamengine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::CStreamEngine( + ACXSTREAM Stream, + ACXDATAFORMAT StreamFormat, + CSimPeakMeter *circuitPeakmeter + ) + : m_PacketsCount(0), + m_PacketSize(0), + m_FirstPacketOffset(0), + m_NotificationTimer(NULL), + m_CurrentState(AcxStreamStateStop), + m_CurrentPacket(0), + m_Position(0), + m_Stream(Stream), + m_StreamFormat(StreamFormat), + m_StartTime(0), + m_StartPosition(0), + m_GlitchAdjust(0), + m_pCircuitPeakmeter(circuitPeakmeter) +{ + PAGED_CODE(); + + KeQueryPerformanceCounter(&m_PerformanceCounterFrequency); + RtlZeroMemory(m_Packets, sizeof(m_Packets)); +} + +_Use_decl_annotations_ +#pragma code_seg() +CStreamEngine::~CStreamEngine() +{ +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AllocateRtPackets( + ULONG PacketCount, + ULONG PacketSize, + PACX_RTPACKET * Packets + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + PVOID packetBuffer = NULL; + PACX_RTPACKET packets = NULL; + + auto exit = scope_exit([&]() { + if (packetBuffer) + { + ExFreePoolWithTag(packetBuffer, DRIVER_TAG); + } + if (packets) + { + FreeRtPackets(packets, PacketCount); + } + }); + + RETURN_NTSTATUS_IF_TRUE(PacketCount > MAX_PACKET_COUNT, STATUS_INVALID_PARAMETER); + + size_t packetsSize = 0; + RETURN_NTSTATUS_IF_FAILED(RtlSizeTMult(PacketCount, sizeof(ACX_RTPACKET), &packetsSize)); + +#pragma prefast(suppress:__WARNING_MEMORY_LEAK, "On error packets gets freed inside scope_exit.") + packets = (PACX_RTPACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, packetsSize, DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(!packets, STATUS_NO_MEMORY); + + // ExAllocatePool2 zeros memory. + + // We need to allocate page-aligned buffers, to ensure no kernel memory leaks + // to user space. Round up the packet size to page aligned, then calculate + // the first packet's buffer offset so packet 0 ends on a page boundary and + // packet 1 begins on a page boundary. + ULONG packetAllocSizeInPages = 0; + ULONG packetAllocSizeInBytes = 0; + ULONG firstPacketOffset = 0; + RETURN_NTSTATUS_IF_FAILED(RtlULongAdd(PacketSize, PAGE_SIZE - 1, &packetAllocSizeInPages)); + + packetAllocSizeInPages = packetAllocSizeInPages / PAGE_SIZE; + packetAllocSizeInBytes = PAGE_SIZE * packetAllocSizeInPages; + firstPacketOffset = packetAllocSizeInBytes - PacketSize; + + ULONG i; + for (i = 0; i < PacketCount; ++i) + { + PMDL pMdl = NULL; + + ACX_RTPACKET_INIT(&packets[i]); + + packetBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, packetAllocSizeInBytes, DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(packetBuffer == NULL, STATUS_NO_MEMORY); + + // ExAllocatePool2 zeros memory. + + pMdl = IoAllocateMdl(packetBuffer, packetAllocSizeInBytes, FALSE, FALSE, NULL); + RETURN_NTSTATUS_IF_TRUE(pMdl == NULL, STATUS_NO_MEMORY); + + MmBuildMdlForNonPagedPool(pMdl); + + WDF_MEMORY_DESCRIPTOR_INIT_MDL( + &((packets)[i].RtPacketBuffer), + pMdl, + packetAllocSizeInBytes); + + packets[i].RtPacketSize = PacketSize; + if (i == 0) + { + packets[i].RtPacketOffset = firstPacketOffset; + } + else + { + packets[i].RtPacketOffset = 0; + } + m_Packets[i] = packetBuffer; + + packetBuffer = NULL; + } + + *Packets = packets; + packets = NULL; + m_PacketsCount = PacketCount; + m_PacketSize = PacketSize; + m_FirstPacketOffset = firstPacketOffset; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +CStreamEngine::FreeRtPackets( + PACX_RTPACKET Packets, + ULONG PacketCount +) +{ + ULONG i; + PVOID buffer; + + PAGED_CODE(); + + for (i = 0; i < PacketCount; ++i) + { + if (Packets[i].RtPacketBuffer.u.MdlType.Mdl) + { + buffer = MmGetMdlVirtualAddress(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + IoFreeMdl(Packets[i].RtPacketBuffer.u.MdlType.Mdl); + ExFreePool(buffer); + } + } + + ExFreePool(Packets); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WDF_TIMER_CONFIG timerConfig; + WDF_OBJECT_ATTRIBUTES timerAttributes; + WDF_TIMER_CONFIG_INIT(&timerConfig, CStreamEngine::s_EvtStreamPassCallback); + timerConfig.AutomaticSerialization = TRUE; + timerConfig.UseHighResolutionTimer = WdfTrue; + timerConfig.Period = 0; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes, STREAM_TIMER_CONTEXT); + timerAttributes.ParentObject = m_Stream; + + RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate( + &timerConfig, + &timerAttributes, + &m_NotificationTimer + )); + + PSTREAM_TIMER_CONTEXT timerCtx; + timerCtx = GetStreamTimerContext(m_NotificationTimer); + timerCtx->StreamEngine = this; + + m_CurrentState = AcxStreamStatePause; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + if (m_NotificationTimer) + { + WdfTimerStop(m_NotificationTimer, TRUE); + WdfObjectDelete(m_NotificationTimer); + m_NotificationTimer = NULL; + } + + KeFlushQueuedDpcs(); + + m_Position = 0; + m_GlitchAdjust = 0; + m_CurrentPacket = 0; + + m_CurrentState = AcxStreamStateStop; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Pause() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"CStreamEngine::Pause - from %d", m_CurrentState); + + RETURN_NTSTATUS_IF_TRUE(m_CurrentState != AcxStreamStateRun, STATUS_INVALID_STATE_TRANSITION); + + m_PeakMeter.StopStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StopStream(); + } + + WdfTimerStop(m_NotificationTimer, TRUE); + + // Save the position we paused at. + UpdatePosition(); + + m_CurrentState = AcxStreamStatePause; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Run() +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + DrvLogInfo(g_SDCAVDspLog, FLAG_STREAM, L"CStreamEngine::Run"); + + if (m_CurrentState != AcxStreamStatePause) + { + status = STATUS_INVALID_STATE_TRANSITION; + return status; + } + + m_PeakMeter.StartStream(); + if (m_pCircuitPeakmeter) + { + m_pCircuitPeakmeter->StartStream(); + } + + // Save the time and position - if we ran and paused previously, the StartTime and StartPosition will allow + // us to continue scheduling packet completions correctly, while still reporting absolute position from the + // start of the stream. + m_StartTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + m_StartPosition = m_Position; + + // Reset time we've lost to glitches + m_GlitchAdjust = 0; + + ScheduleNextPass(); + + m_CurrentState = AcxStreamStateRun; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetPresentationPosition( + PULONGLONG PositionInBlocks, + PULONGLONG QPCPosition +) +{ + PAGED_CODE(); + + DrvLogVerbose(g_SDCAVDspLog, FLAG_STREAM, L"CStreamEngine::GetPresentationPosition"); + + ULONG blockAlign; + LARGE_INTEGER qpc; + + blockAlign = AcxDataFormatGetBlockAlign(m_StreamFormat); + qpc = KeQueryPerformanceCounter(NULL); + + // Update the position based on the current time + UpdatePosition(); + + *PositionInBlocks = m_Position / blockAlign; + + *QPCPosition = (ULONGLONG)qpc.QuadPart; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + UNREFERENCED_PARAMETER(DrmRights); + + // + // At this point the driver should enforce the new DrmRights. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // + // 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 AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetHWLatency( + ULONG * FifoSize, + ULONG * Delay +) +{ + PAGED_CODE(); + + *FifoSize = 128; + *Delay = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CSimPeakMeter * +CStreamEngine::GetPeakMeter() +{ + PAGED_CODE(); + + return &m_PeakMeter; +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +CStreamEngine::s_EvtStreamPassCallback( + WDFTIMER Timer +) +{ + CStreamEngine * This; + PSTREAM_TIMER_CONTEXT timerCtx; + + // Get our stream engine pointer from the timer context + timerCtx = GetStreamTimerContext(Timer); + This = timerCtx->StreamEngine; + + // Call the StreamPassCallback for the engine + This->StreamPassCallback(); +} + +// This is run every time the stream timer fires +_Use_decl_annotations_ +#pragma code_seg() +VOID +CStreamEngine::StreamPassCallback() +{ + ULONGLONG completedPacket; + ULONGLONG qpcCompleted; + + // Save the time at which we moved to the next packet + qpcCompleted = (ULONGLONG)KeQueryPerformanceCounter(NULL).QuadPart; + + // Process the packet (e.g. save render to file/generate capture data) + ProcessPacket(); + + // We've completed a packet! Increment our currently active packet + completedPacket = (ULONG)InterlockedIncrement((LONG*)&m_CurrentPacket) - 1; + + InterlockedExchange64(&m_LastPacketStart.QuadPart, m_CurrentPacketStart.QuadPart); + InterlockedExchange64(&m_CurrentPacketStart.QuadPart, qpcCompleted); + + // Tell ACX we've completed the packet. + (void)AcxRtStreamNotifyPacketComplete(m_Stream, completedPacket, qpcCompleted); + + // Schedule when our new current packet will finish + ScheduleNextPass(); +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +CStreamEngine::ScheduleNextPass() +{ + LONGLONG delay = 0; + ULONG bytesPerSecond; + ULONGLONG nextPacket = 0; + ULONGLONG nextPacketStartPosition = 0; + ULONGLONG nextPacketPositionFromLastPause = 0; + ULONGLONG nextPacketTimeFromLastPauseHns = 0; + ULONGLONG nextPacketTime = 0; + ULONGLONG currentTime; + BOOLEAN inTimerQueue = FALSE; + + // Get the number of bytes per second from our stored stream format + bytesPerSecond = GetBytesPerSecond(); + + // Calculate the absolute position of the beginning of the next packet from the beginning of the stream + nextPacket = m_CurrentPacket + 1; + nextPacketStartPosition = nextPacket * m_PacketSize; + + // Adjust next packet position to account for the last time we resumed from Pause + nextPacketPositionFromLastPause = nextPacketStartPosition - m_StartPosition; + + // Convert from bytes to HNS (to prevent truncation, multiply first then divide) + nextPacketTimeFromLastPauseHns = nextPacketPositionFromLastPause * HNS_PER_SEC / bytesPerSecond; + + // Next packet time is Time @ resume from Pause, offset for lost time due to glitch, with next packet time added + nextPacketTime = m_StartTime + m_GlitchAdjust + nextPacketTimeFromLastPauseHns; + + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Determine how long we want to wait, in HNS. Negative since it's a relative wait + delay = -(LONGLONG)(nextPacketTime - currentTime); + + // If the delay isn't negative, this means we lost some time (e.g. broken into kernel debugger). Update + // our glitch adjust to account for that lost time, and attempt to schedule again + if (delay >= 0) + { + // Glitch!!! + // Update the glitch adjustment and set the new delay. + m_GlitchAdjust += delay; + + StreamPassCallback(); + + return; + } + + // Start the timer for our next pass! Note the timer isn't periodic. + inTimerQueue = WdfTimerStart(m_NotificationTimer, delay); + + // We shouldn't be scheduling our next pass if the timer was previously still pending + ASSERT(inTimerQueue == FALSE); +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +CStreamEngine::UpdatePosition() +{ + ULONGLONG currentTime; + ULONG bytesPerSecond; + + if (m_CurrentState != AcxStreamStateRun) + { + return; + } + bytesPerSecond = GetBytesPerSecond(); + currentTime = KSCONVERT_PERFORMANCE_TIME(m_PerformanceCounterFrequency.QuadPart, KeQueryPerformanceCounter(NULL)); + + // Update position + m_Position = m_StartPosition - m_GlitchAdjust + (currentTime - m_StartTime) * bytesPerSecond / HNS_PER_SEC; +} + +_Use_decl_annotations_ +#pragma code_seg() +ULONG +CStreamEngine::GetBytesPerSecond() +{ + ULONG bytesPerSecond; + + bytesPerSecond = AcxDataFormatGetAverageBytesPerSec(m_StreamFormat); + + return bytesPerSecond; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetCurrentPacket( + PULONG CurrentPacket + ) +{ + ULONG currentPacket; + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + *CurrentPacket = currentPacket; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::CRenderStreamEngine( + ACXSTREAM Stream, + ACXDATAFORMAT StreamFormat, + CSimPeakMeter *circuitPeakmeter + ) + : CStreamEngine(Stream, StreamFormat, circuitPeakmeter) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::~CRenderStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + + // ignore failure + RETURN_NTSTATUS_IF_FAILED(m_SaveData.SetDataFormat((PKSDATAFORMAT)AcxDataFormatGetKsDataFormat(m_StreamFormat))); + + // ignore failure + RETURN_NTSTATUS_IF_FAILED(m_SaveData.Initialize(FALSE)); + + // ignore failure + RETURN_NTSTATUS_IF_FAILED(m_SaveData.SetMaxWriteSize(m_PacketSize * m_PacketsCount * 16)); + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_SaveData.WaitAllWorkItems(); + m_SaveData.Cleanup(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::AssignDrmContentId( + ULONG DrmContentId, + PACXDRMRIGHTS DrmRights + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + + // + // 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. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // Loopback: if CopyProtect is true, disable loopback stream. + // + + // + // 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 AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::SetRenderPacket( + ULONG Packet, + ULONG Flags, + ULONG EosPacketLength + ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(EosPacketLength); + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + if (Packet <= currentPacket) + { + //ASSERT(FALSE); + status = STATUS_DATA_LATE_ERROR; + } + else if (Packet > currentPacket + 1) + { + //ASSERT(FALSE); + status = STATUS_DATA_OVERRUN; + } + + return status; +} + +_Use_decl_annotations_ +#pragma code_seg() +NTSTATUS +CRenderStreamEngine::GetLinearBufferPosition( + _Out_ PULONGLONG Position +) +{ + NTSTATUS status; + ULONGLONG qpcIgnored = 0; + + // For this sample, we're borrowing the Presentation Position. + // An actual device would return the position of the last byte + // read from the audio buffer, not the last byte presented to the user + status = GetPresentationPosition(Position, &qpcIgnored); + if (!NT_SUCCESS(status)) + { + return status; + } + + *Position *= AcxDataFormatGetBlockAlign(m_StreamFormat); + + return STATUS_SUCCESS; + +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +CRenderStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + m_SaveData.WriteData(packetBuffer, m_PacketSize); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::CCaptureStreamEngine( + ACXSTREAM Stream, + ACXDATAFORMAT StreamFormat + ) + : CStreamEngine(Stream, StreamFormat, nullptr), + m_EnableWaveCapture(0) +{ + PAGED_CODE(); + + m_CurrentPacketStart.QuadPart = 0; + m_LastPacketStart.QuadPart = 0; + + RtlInitUnicodeString(&m_HostCaptureFileName, NULL); + RtlInitUnicodeString(&m_LoopbackCaptureFileName, NULL); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::~CCaptureStreamEngine() +{ + PAGED_CODE(); + + RtlFreeUnicodeString(&m_HostCaptureFileName); + RtlFreeUnicodeString(&m_LoopbackCaptureFileName); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + + RETURN_NTSTATUS_IF_FAILED(ReadRegistrySettings()); + + if (m_EnableWaveCapture) + { + status = m_WaveReader.Init((PWAVEFORMATEXTENSIBLE)AcxDataFormatGetWaveFormatExtensible(m_StreamFormat), + &m_HostCaptureFileName); + if (!NT_SUCCESS(status)) + { + m_EnableWaveCapture = FALSE; + } + } + + if (!m_EnableWaveCapture) + { + status = m_ToneGenerator.Init(DEFAULT_FREQUENCY, (PWAVEFORMATEXTENSIBLE)AcxDataFormatGetWaveFormatExtensible(m_StreamFormat)); + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + if (m_EnableWaveCapture) + { + m_WaveReader.WaitAllWorkItems(); + } + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::GetCapturePacket( + ULONG * LastCapturePacket, + ULONGLONG * QPCPacketStart, + BOOLEAN * MoreData + ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG currentPacket; + LONGLONG qpcPacketStart; + + PAGED_CODE(); + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + qpcPacketStart = InterlockedCompareExchange64(&m_LastPacketStart.QuadPart, -1, -1); + + *LastCapturePacket = currentPacket - 1; + *QPCPacketStart = (ULONGLONG)qpcPacketStart; + *MoreData = FALSE; + + return status; +} + +_Use_decl_annotations_ +#pragma code_seg() +VOID +CCaptureStreamEngine::ProcessPacket() +{ + ULONG currentPacket; + ULONG packetIndex; + PBYTE packetBuffer; + + currentPacket = (ULONG)InterlockedCompareExchange((LONG*)&m_CurrentPacket, -1, -1); + + packetIndex = currentPacket % m_PacketsCount; + packetBuffer = (PBYTE)m_Packets[packetIndex]; + + // Packet 0 starts at an offset if the size isn't a multiple of page_size + if (packetIndex == 0) + { + packetBuffer += m_FirstPacketOffset; + } + + if (m_EnableWaveCapture) + { + m_WaveReader.ReadWaveData(packetBuffer, m_PacketSize); + } + else + { + m_ToneGenerator.GenerateSine(packetBuffer, m_PacketSize); + } +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReadRegistrySettings() +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // TRUE only on SUCCESS + m_EnableWaveCapture = FALSE; + + RTL_QUERY_REGISTRY_TABLE paramTable[] = { + // QueryRoutine Flags Name EntryContext DefaultType DefaultData DefaultLength + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"EnableWaveCapture", &m_EnableWaveCapture, (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_DWORD, &m_EnableWaveCapture, sizeof(DWORD) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"HostCaptureFileName", &m_HostCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_HostCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_TYPECHECK, L"LoopbackCaptureFileName", &m_LoopbackCaptureFileName, (REG_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_SZ, &m_LoopbackCaptureFileName, sizeof(UNICODE_STRING) }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + UNICODE_STRING parametersPath; + RtlInitUnicodeString(¶metersPath, 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); + +#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit") + parametersPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, parametersPath.MaximumLength, DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(parametersPath.Buffer == NULL, STATUS_INSUFFICIENT_RESOURCES); + auto parametersPath_free = scope_exit([¶metersPath]() { + ExFreePool(parametersPath.Buffer); + }); + + // ExAllocatePool2 zeros memory. + + RtlAppendUnicodeToString(¶metersPath, g_RegistryPath.Buffer); + RtlAppendUnicodeToString(¶metersPath, L"\\Parameters"); + + RETURN_NTSTATUS_IF_FAILED(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + parametersPath.Buffer, + ¶mTable[0], + NULL, + NULL)); + + m_EnableWaveCapture = TRUE; + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector * KeywordDetector + + ) + : CCaptureStreamEngine(Stream, StreamFormat), + m_KeywordDetector(KeywordDetector) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CBufferedCaptureStreamEngine::~CBufferedCaptureStreamEngine() +{ + PAGED_CODE(); +} + +// This is run every time the stream timer fires +_Use_decl_annotations_ +#pragma code_seg() +VOID +CBufferedCaptureStreamEngine::StreamPassCallback() +{ + LARGE_INTEGER qpc; + LARGE_INTEGER qpcFrequency; + BOOLEAN isRealtime = FALSE; + ULONGLONG completedPacket; + LONGLONG NewPacketNumber; + ULONGLONG NewPerformanceCount; + + qpc = KeQueryPerformanceCounter(&qpcFrequency); + + // As this is a simulation, we still want the ScheduleNextPass to + // keep producing data. To that end, update the current packet + // information used for production. + completedPacket = (ULONG)InterlockedIncrement((LONG*)&m_CurrentPacket) - 1; + InterlockedExchange64(&m_LastPacketStart.QuadPart, m_CurrentPacketStart.QuadPart); + InterlockedExchange64(&m_CurrentPacketStart.QuadPart, qpc.QuadPart); + + + // Add the next packet to the fifo queue + m_KeywordDetector->DpcRoutine(qpc.QuadPart, qpcFrequency.QuadPart, &isRealtime, &NewPacketNumber, &NewPerformanceCount); + + if (isRealtime && (m_CurrentState == AcxStreamStateRun)) + { + // We are running real time and just completed a packet, so notify. + (void)AcxRtStreamNotifyPacketComplete(m_Stream, NewPacketNumber, NewPerformanceCount); + } + + // Schedule when our new current packet will finish + ScheduleNextPass(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Pause() +{ + PAGED_CODE(); + + m_KeywordDetector->Stop(); + return CCaptureStreamEngine::Pause(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::Run() +{ + PAGED_CODE(); + ULONG FrontCapturePacket; + ULONGLONG QPCFrontPacket; + + m_KeywordDetector->Run(); + NTSTATUS status = CCaptureStreamEngine::Run(); + + NTSTATUS fifoStatus = m_KeywordDetector->GetFifoStart(&FrontCapturePacket, &QPCFrontPacket); + if (NT_SUCCESS(fifoStatus)) + { + // We just entered the run state, so we need to trigger the packet completion for the first + // buffer in the fifo + (void)AcxRtStreamNotifyPacketComplete(m_Stream, FrontCapturePacket, QPCFrontPacket); + } + + return status; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CBufferedCaptureStreamEngine::GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ) +{ + PAGED_CODE(); + ULONG nextPacketNumber; + ULONGLONG nextQPCCount; + + // retrieve the packet from the fifo queue + NTSTATUS status = m_KeywordDetector->GetReadPacket(m_PacketsCount, m_PacketSize, m_Packets, LastCapturePacket, QPCPacketStart, MoreData, &nextPacketNumber, &nextQPCCount); + + if (NT_SUCCESS(status) && MoreData) + { + (void)AcxRtStreamNotifyPacketComplete(m_Stream, nextPacketNumber, nextQPCCount); + } + + return status; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.h b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.h new file mode 100644 index 00000000..902bb007 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVDsp/streamengine.h @@ -0,0 +1,391 @@ +/*++ + + 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: + + streamengine.h + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ +#pragma once + +#include "savedata.h" +#include "tonegenerator.h" +#include "WaveReader.h" +#include "SimPeakMeter.h" +#include "KeywordDetector.h" + +#define HNSTIME_PER_MILLISECOND 10000 + +#define MAX_PACKET_COUNT 2 + +#define DEFAULT_FREQUENCY (220) +#define LOOPBACK_FREQUENCY (500) +#define DEFAULT_FREQUENCY (220) + +class CStreamEngine +{ +public: + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AllocateRtPackets( + _In_ ULONG PacketCount, + _In_ ULONG PacketSize, + _Out_ PACX_RTPACKET * Packets + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + VOID + FreeRtPackets( + _Frees_ptr_ PACX_RTPACKET Packets, + _In_ ULONG PacketCount + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetPresentationPosition( + _Out_ PULONGLONG PositionInBlocks, + _Out_ PULONGLONG QPCPosition + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCurrentPacket( + _Out_ PULONG CurrentPacket + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + NTSTATUS + GetLinearBufferPosition( + _Out_ PULONGLONG Position + ) + { + UNREFERENCED_PARAMETER(Position); + return STATUS_NOT_SUPPORTED; + } + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CSimPeakMeter * + GetPeakMeter(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_opt_ CSimPeakMeter *circuitPeakmeter + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + ~CStreamEngine(); + +protected: + PVOID m_Packets[MAX_PACKET_COUNT]{ nullptr }; + ULONG m_PacketsCount{ 0 }; + ULONG m_PacketSize{ 0 }; + ULONG m_FirstPacketOffset{ 0 }; + WDFTIMER m_NotificationTimer{ nullptr }; + ACX_STREAM_STATE m_CurrentState{ AcxStreamStateStop }; + ULONG m_CurrentPacket{ 0 }; + ULONGLONG m_Position{ 0 }; + ACXSTREAM m_Stream{ nullptr }; + ACXDATAFORMAT m_StreamFormat{ nullptr }; + ULONGLONG m_StartTime{ 0 }; + ULONGLONG m_StartPosition{ 0 }; + ULONGLONG m_GlitchAdjust{ 0 }; + LARGE_INTEGER m_PerformanceCounterFrequency{ 0 }; + LARGE_INTEGER m_CurrentPacketStart{ 0 }; + LARGE_INTEGER m_LastPacketStart{ 0 }; + CSimPeakMeter m_PeakMeter; + CSimPeakMeter* m_pCircuitPeakmeter{ nullptr }; + + static + __drv_maxIRQL(DISPATCH_LEVEL) + _Function_class_(EVT_WDF_TIMER) + #pragma code_seg() + VOID s_EvtStreamPassCallback( + _In_ WDFTIMER Timer + ); + + // This is run every time the stream timer fires + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + StreamPassCallback(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ScheduleNextPass(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + UpdatePosition(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + ULONG + GetBytesPerSecond(); + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ProcessPacket() = 0; +}; + +class CRenderStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CSimPeakMeter *circuitPeakmeter + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CRenderStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + SetRenderPacket( + _In_ ULONG Packet, + _In_ ULONG Flags, + _In_ ULONG EosPacketLength + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + #pragma code_seg() + NTSTATUS + GetLinearBufferPosition( + _Out_ PULONGLONG Position + ); + +protected: + CSaveData m_SaveData; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ProcessPacket(); + +}; + +class CCaptureStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + ToneGenerator m_ToneGenerator; + CWaveReader m_WaveReader; + DWORD m_EnableWaveCapture{ 0 }; + UNICODE_STRING m_HostCaptureFileName{ 0 }; + UNICODE_STRING m_LoopbackCaptureFileName{ 0 }; + + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ProcessPacket(); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReadRegistrySettings(); +}; + +class CBufferedCaptureStreamEngine : public CCaptureStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CBufferedCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat, + _In_ CKeywordDetector * KeywordDetector + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CBufferedCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetCapturePacket( + _Out_ ULONG * LastCapturePacket, + _Out_ ULONGLONG * QPCPacketStart, + _Out_ BOOLEAN * MoreData + ); + +protected: + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + ProcessPacket() {} + + // This is run every time the stream timer fires + virtual + __drv_maxIRQL(DISPATCH_LEVEL) + #pragma code_seg() + VOID + StreamPassCallback(); + + CKeywordDetector * m_KeywordDetector{ nullptr }; +}; + + +// Define DSP circuit/stream pin context. +// +typedef struct _STREAM_TIMER_CONTEXT { + CStreamEngine * StreamEngine; +} STREAM_TIMER_CONTEXT, *PSTREAM_TIMER_CONTEXT; + +#pragma code_seg() +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(STREAM_TIMER_CONTEXT, GetStreamTimerContext) diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.cpp new file mode 100644 index 00000000..73f15aaf --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.cpp @@ -0,0 +1,405 @@ +/*++ + + 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: + + AudioModule.cpp + +Abstract: + + Implementation of general purpose audio module property handlers + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "audiomodule.h" +#include "stdunk.h" +#include <ks.h> + +AUDIOMODULE_PARAMETER_INFO AudioModule_ParameterInfo[] = +{ + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_SET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE_CONTEXT, Parameter1), + VT_UI4, + AudioModule_ValidParameterList, + SIZEOF_ARRAY(AudioModule_ValidParameterList) + }, + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE_CONTEXT, Parameter2), + VT_UI1, + NULL, + 0 + }, +}; + +AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[] = +{ + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_SET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE0_CONTEXT, Parameter1), + VT_UI4, + AudioModule0_ValidParameterList, + SIZEOF_ARRAY(AudioModule0_ValidParameterList) + }, + { + ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE0_CONTEXT, Parameter2), + VT_UI1, + NULL, + 0 + }, +}; + +AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE1_CONTEXT, Parameter1), + VT_UI1, + AudioModule1_ValidParameterList, + SIZEOF_ARRAY(AudioModule1_ValidParameterList) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE1_CONTEXT, Parameter2), + VT_UI8, + NULL, + 0 + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE1_CONTEXT, Parameter3), + VT_UI4, + NULL, + 0 + }, +}; + +AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[] = +{ + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE2_CONTEXT, Parameter1), + VT_UI4, + AudioModule2_ValidParameterList, + SIZEOF_ARRAY(AudioModule2_ValidParameterList) + }, + { + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + 0, + (ULONG)RTL_FIELD_SIZE(SDCAXU_AUDIOMODULE2_CONTEXT, Parameter2), + VT_UI2, + NULL, + 0 + }, +}; + + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ) +{ + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG cbFullProperty = 0; + ULONG cbDataListSize = 0; + + PAGED_CODE(); + + ASSERT(ParameterInfo); + ASSERT(BufferCb); + + // + // Compute total size of property. + // + ntStatus = RtlULongMult(ParameterInfo->Size, + ParameterInfo->ValidSetCount, + &cbDataListSize); + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + ntStatus = RtlULongAdd(cbDataListSize, + (ULONG)(sizeof(KSPROPERTY_DESCRIPTION) + + sizeof(KSPROPERTY_MEMBERSHEADER)), + &cbFullProperty); + + if (!NT_SUCCESS(ntStatus)) + { + ASSERT(FALSE); + *BufferCb = 0; + return ntStatus; + } + + // + // Return the info the caller is asking for. + // + if (*BufferCb == 0) + { + // caller wants to know the size of the buffer. + *BufferCb = cbFullProperty; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (*BufferCb >= (sizeof(KSPROPERTY_DESCRIPTION))) + { + PKSPROPERTY_DESCRIPTION propDesc = PKSPROPERTY_DESCRIPTION(Buffer); + + propDesc->AccessFlags = ParameterInfo->AccessFlags; + propDesc->DescriptionSize = cbFullProperty; + propDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + propDesc->PropTypeSet.Id = ParameterInfo->VtType; + propDesc->PropTypeSet.Flags = 0; + propDesc->MembersListCount = 1; + propDesc->Reserved = 0; + + // if return buffer can also hold a list description, return it too + if(*BufferCb >= cbFullProperty) + { + // fill in the members header + PKSPROPERTY_MEMBERSHEADER members = + PKSPROPERTY_MEMBERSHEADER(propDesc + 1); + + members->MembersFlags = KSPROPERTY_MEMBER_VALUES; + members->MembersSize = ParameterInfo->Size; + members->MembersCount = ParameterInfo->ValidSetCount; + members->Flags = KSPROPERTY_MEMBER_FLAG_DEFAULT; + + // fill in valid array. + BYTE* array = (BYTE*)(members + 1); + + RtlCopyMemory(array, ParameterInfo->ValidSet, cbDataListSize); + + // set the return value size + *BufferCb = cbFullProperty; + } + else + { + *BufferCb = sizeof(KSPROPERTY_DESCRIPTION); + } + } + else if(*BufferCb >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + PULONG accessFlags = PULONG(Buffer); + + *BufferCb = sizeof(ULONG); + *accessFlags = ParameterInfo->AccessFlags; + } + else + { + *BufferCb = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + + return ntStatus; +} + +#pragma code_seg("PAGE") +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ) +{ + PAGED_CODE(); + + ULONG i = 0; + ULONG j = 0; + BOOLEAN validParam = FALSE; + + // + // Validate buffer ptr and size. + // + if (Buffer == NULL || BufferCb == 0) + { + validParam = FALSE; + goto exit; + } + + // + // Check its size. + // + if (BufferCb < ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + + // + // Check the valid list. + // + if (ParameterInfo->ValidSet && ParameterInfo->ValidSetCount) + { + BYTE* buffer = (BYTE*)ParameterInfo->ValidSet; + BYTE* pattern = (BYTE*)Buffer; + + // + // Scan the valid list. + // + for (i = 0; i < ParameterInfo->ValidSetCount; ++i) + { + for (j=0; j < ParameterInfo->Size; ++j) + { + if (buffer[j] != pattern[j]) + { + break; + } + } + + if (j == ParameterInfo->Size) + { + // got a match. + break; + } + + buffer += ParameterInfo->Size; + } + + // + // If end of list, we didn't find the value. + // + if (i == ParameterInfo->ValidSetCount) + { + validParam = FALSE; + goto exit; + } + } + else + { + // + // Negative-testing support. Fail request if value is -1. + // + BYTE* buffer = (BYTE*)Buffer; + + for (i = 0; i < ParameterInfo->Size; ++i) + { + if (buffer[i] != 0xFF) + { + break; + } + } + + // + // If value is -1, return error. + // + if (i == ParameterInfo->Size) + { + validParam = FALSE; + goto exit; + } + } + + validParam = TRUE; + +exit: + return validParam; +} + +#pragma code_seg("PAGE") +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ParameterId); + + *ParameterChanged = FALSE; + + // Handle KSPROPERTY_TYPE_BASICSUPPORT query + if (Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + return AudioModule_GenericHandler_BasicSupport(ParameterInfo, OutBuffer, OutBufferCb); + } + + ULONG cbMinSize = ParameterInfo->Size; + + if (Verb & KSPROPERTY_TYPE_GET) + { + // Verify module parameter supports 'get'. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_GET)) + { + *OutBufferCb = 0; + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Verify value size + if (*OutBufferCb == 0) + { + *OutBufferCb = cbMinSize; + return STATUS_BUFFER_OVERFLOW; + } + if (*OutBufferCb < cbMinSize) + { + *OutBufferCb = 0; + return STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory(OutBuffer, CurrentValue, ParameterInfo->Size); + *OutBufferCb = cbMinSize; + return STATUS_SUCCESS; + } + } + else if (Verb & KSPROPERTY_TYPE_SET) + { + *OutBufferCb = 0; + + // Verify it is a write prop. + if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_SET)) + { + return STATUS_INVALID_DEVICE_REQUEST; + } + + // Validate parameter. + if (!IsAudioModuleParameterValid(ParameterInfo, InBuffer, InBufferCb)) + { + return STATUS_INVALID_PARAMETER; + } + + if (ParameterInfo->Size != + RtlCompareMemory(CurrentValue, InBuffer, ParameterInfo->Size)) + { + RtlCopyMemory(CurrentValue, InBuffer, ParameterInfo->Size); + *ParameterChanged = TRUE; + } + + return STATUS_SUCCESS; + } + + return STATUS_INVALID_DEVICE_REQUEST; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.h new file mode 100644 index 00000000..11fd7c3b --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/AudioModule.h @@ -0,0 +1,246 @@ +/*++ + +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: + + AudioModule.h + +Abstract: + + Contains audio modules definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#ifndef _AUDIOMODULE_H_ +#define _AUDIOMODULE_H_ + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +// Audio module definitions + +// +// Audio module instance defintion. +// + +// top 8 bits reserved for use by aggregation +// next 12 bits are the config id mask +// bottom 12 bits instance id +#define AUDIOMODULE_CLASS_CFG_ID_MASK 0xFFF +#define AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK 0xFFF + +#define AUDIOMODULE_INSTANCE_ID(ClassCfgId, ClassCfgInstanceId) \ + ((ULONG(ClassCfgId & AUDIOMODULE_CLASS_CFG_ID_MASK) << 12) | \ + (ULONG(ClassCfgInstanceId & AUDIOMODULE_CLASS_CFG_INSTANCE_ID_MASK))) + +#define AUDIOMODULE_GET_CLASSCFGID(InstanceId) \ + (ULONG(InstanceId) >> 12 & AUDIOMODULE_CLASS_CFG_ID_MASK) + +enum AudioModule_Parameter { + AudioModuleParameter1 = 0, + AudioModuleParameter2, + AudioModuleParameter3 +}; + +typedef struct _AUDIOMODULE_CUSTOM_COMMAND { + ULONG Verb; // get, set and support + AudioModule_Parameter ParameterId; +} AUDIOMODULE_CUSTOM_COMMAND, *PAUDIOMODULE_CUSTOM_COMMAND; + +enum AudioModule_Notification_Type { + AudioModuleParameterChanged = 0, +}; + +typedef struct _AUDIOMODULE_CUSTOM_NOTIFICATION { + ULONG Type; + union + { + struct + { + ULONG ParameterId; + } ParameterChanged; + }; +} AUDIOMODULE_CUSTOM_NOTIFICATION, *PAUDIOMODULE_CUSTOM_NOTIFICATION; + +#define AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION 0x00000001 + +typedef struct _SDCAXU_AUDIOMODULE_CONTEXT { + ACXPNPEVENT Event; + ULONG Parameter1; + BYTE Parameter2; + ULONG InstanceId; + ACXCIRCUIT Circuit; +} SDCAXU_AUDIOMODULE_CONTEXT, *PSDCAXU_AUDIOMODULE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_AUDIOMODULE_CONTEXT, GetSdcaXuAudioModuleContext); + +typedef struct _SDCAXU_AUDIOMODULE0_CONTEXT { + ACXPNPEVENT Event; + ULONG Parameter1; + BYTE Parameter2; + ULONG InstanceId; + ACXCIRCUIT Circuit; +} SDCAXU_AUDIOMODULE0_CONTEXT, *PSDCAXU_AUDIOMODULE0_CONTEXT; + +typedef struct _SDCAXU_AUDIOMODULE1_CONTEXT { + ACXPNPEVENT Event; + BYTE Parameter1; + ULONGLONG Parameter2; + DWORD Parameter3; + ULONG InstanceId; + ACXCIRCUIT Circuit; +} SDCAXU_AUDIOMODULE1_CONTEXT, *PSDCAXU_AUDIOMODULE1_CONTEXT; + +typedef struct _SDCAXU_AUDIOMODULE2_CONTEXT { + ACXPNPEVENT Event; + ULONG Parameter1; + USHORT Parameter2; + ULONG InstanceId; + ACXCIRCUIT Circuit; +} SDCAXU_AUDIOMODULE2_CONTEXT, *PSDCAXU_AUDIOMODULE2_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_AUDIOMODULE0_CONTEXT, GetSdcaXuAudioModule0Context); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_AUDIOMODULE1_CONTEXT, GetSdcaXuAudioModule1Context); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_AUDIOMODULE2_CONTEXT, GetSdcaXuAudioModule2Context); + +typedef struct _AUDIOMODULE_PARAMETER_INFO +{ + USHORT AccessFlags; // get/set/basic-support attributes. + USHORT Flags; + ULONG Size; + DWORD VtType; + PVOID ValidSet; + ULONG ValidSetCount; +} AUDIOMODULE_PARAMETER_INFO, *PAUDIOMODULE_PARAMETER_INFO; + +// +// factory Module definitions +// +#define AUDIOMODULEDESCRIPTION L"Generic system module" +#define AUDIOMODULE_MAJOR 0x1 +#define AUDIOMODULE_MINOR 0X0 +static const GUID AudioModuleId = +{ 0xe24c8b6f, 0xede7, 0x4255, 0x8b, 0x39, 0x77, 0x97, 0x60, 0x15, 0xd5, 0x93 }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND SdcaXu_EvtProcessCommand; + +static +ULONG AudioModule_ValidParameterList[] = +{ + 1, 2, 5 +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule_ParameterInfo[2]; + + +// +// render Module 0 definitions +// +#define AUDIOMODULE0DESCRIPTION L"Generic system module" +#define AUDIOMODULE0_MAJOR 0x1 +#define AUDIOMODULE0_MINOR 0X0 + +// {D96F901A-BFDD-46FD-9B1E-4FCD9D693360} +static const GUID AudioModule0Id = +{ 0xd96f901a, 0xbfdd, 0x46fd, { 0x9b, 0x1e, 0x4f, 0xcd, 0x9d, 0x69, 0x33, 0x60 } }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND SdcaXu_EvtProcessCommand0; + +static +ULONG AudioModule0_ValidParameterList[] = +{ + 1, 2, 5 +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[2]; + +// +// render Module 1 definitions +// +static +BYTE AudioModule1_ValidParameterList[] = +{ + 0, 1, 2 +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[3]; + +#define AUDIOMODULE1DESCRIPTION L"Module 1" +#define AUDIOMODULE1_MAJOR 0x2 +#define AUDIOMODULE1_MINOR 0X1 + +// {631A7961-DED6-4405-9A37-E4C4380918E4} +static const GUID AudioModule1Id = +{ 0x631a7961, 0xded6, 0x4405, { 0x9a, 0x37, 0xe4, 0xc4, 0x38, 0x9, 0x18, 0xe4 } }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND SdcaXu_EvtProcessCommand1; + +// +// render Module 2 definitions +// +static +ULONG AudioModule2_ValidParameterList[] = +{ + 1, 0xfffffffe +}; + +extern AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[2]; + +#define AUDIOMODULE2DESCRIPTION L"Module 2" +#define AUDIOMODULE2_MAJOR 0x2 +#define AUDIOMODULE2_MINOR 0X0 + +// {3471D6C5-6322-4730-8FD3-177061B52BB5} +static const GUID AudioModule2Id = +{ 0x3471d6c5, 0x6322, 0x4730, { 0x8f, 0xd3, 0x17, 0x70, 0x61, 0xb5, 0x2b, 0xb5 } }; + +EVT_ACX_AUDIOMODULE_PROCESSCOMMAND SdcaXu_EvtProcessCommand2; + +// General purpose helper functions + +NTSTATUS +AudioModule_GenericHandler_BasicSupport( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer, + _Inout_ ULONG * BufferCb + ); + +BOOLEAN +IsAudioModuleParameterValid( + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _In_reads_bytes_opt_(BufferCb) PVOID Buffer, + _In_ ULONG BufferCb + ); + +NTSTATUS +AudioModule_GenericHandler( + _In_ ULONG Verb, + _In_ ULONG ParameterId, + _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo, + _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue, + _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer, + _In_ ULONG InBufferCb, + _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer, + _Inout_ ULONG * OutBufferCb, + _In_ BOOL * ParameterChanged + ); + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +#endif // _AUDIOMODULE_H_ diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.cpp new file mode 100644 index 00000000..df0d2c90 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.cpp @@ -0,0 +1,464 @@ +/*++ + + 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: + + CircuitDevice.cpp + +Abstract: + + Raw PDO for ACX circuits. This file contains routines to create Device + and handle pnp requests + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include "modulecircuit.h" + +#include "CircuitDevice.h" + +#include "SdcaVXuTestInterface.h" + +#ifndef __INTELLISENSE__ +#include "CircuitDevice.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS +SDCAVXu_CreateCircuitDevice( + _In_ WDFDEVICE Device +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE circuitDevice = NULL; + + auto exit = scope_exit([&status, &circuitDevice]() { + if (!NT_SUCCESS(status)) + { + if (circuitDevice != NULL) + { + WdfObjectDelete(circuitDevice); + } + } + }); + + // + // Create a child audio device for this circuit. + // + PWDFDEVICE_INIT devInit = NULL; + devInit = WdfPdoInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == devInit, STATUS_INSUFFICIENT_RESOURCES); + + auto devInit_free = scope_exit([&devInit, &status]() { + WdfDeviceInitFree(devInit); + }); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &CircuitHardwareId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(devInit, &CircuitDeviceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddCompatibleID(devInit, &CircuitCompatibleId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(devInit, &CircuitInstanceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignContainerID(devInit, &CircuitContainerId)); + + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(devInit, + &CircuitDeviceDescription, + &CircuitDeviceLocation, + 0x409)); + + WdfPdoInitSetDefaultLocale(devInit, 0x409); + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG acxDevInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&acxDevInitCfg); + acxDevInitCfg.Flags |= AcxDeviceInitConfigRawDevice; + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(devInit, &acxDevInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = SdcaXuCircuit_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = SdcaXuCircuit_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = SdcaXuCircuit_EvtDeviceSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(devInit, &pnpPowerCallbacks); + + // + // Specify a context for this circuit device. + // + WDF_OBJECT_ATTRIBUTES attributes; + attributes.ParentObject = Device; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_CIRCUIT_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuCircuit_EvtDeviceContextCleanup; + attributes.ExecutionLevel = WdfExecutionLevelPassive; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&devInit, &attributes, &circuitDevice)); + + // + // devInit attached to device, no need to free + // + devInit_free.release(); + + // + // Tell the framework to set the NoDisplayInUI in the DeviceCaps so + // that the device does not show up in Device Manager. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.NoDisplayInUI = WdfTrue; + WdfDeviceSetPnpCapabilities(circuitDevice, &pnpCaps); + + // + // Init circuit's device context. + // + PSDCAXU_CIRCUIT_DEVICE_CONTEXT circuitDeviceContext; + circuitDeviceContext = GetCircuitDeviceContext(circuitDevice); + ASSERT(circuitDeviceContext != NULL); + circuitDeviceContext->FirstTimePrepareHardware = TRUE; + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(circuitDevice, &devCfg)); + + // + // Add circuitDevice to Device's dynamic circuit device list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuitDevice(Device, circuitDevice)); + + PSDCAXU_DEVICE_CONTEXT deviceContext; + deviceContext = GetSdcaXuDeviceContext(Device); + deviceContext->CircuitDevice = circuitDevice; + + // + // Add the RAWCONTROL interface to this device + // + RETURN_NTSTATUS_IF_FAILED(SdcaXu_ConfigureTestInterface(circuitDevice, &GUID_DEVINTERFACE_SDCAVXU_TEST_RAWCONTROL)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtIoctlInterfaceTest( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request +) +{ + PAGED_CODE(); + + size_t cbOutputBuffer = 0; + ULONG * input = nullptr; + ULONG * output = nullptr; + ULONG temp = 0; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Received test IOCTL for device %p", Device); + + RETURN_NTSTATUS_IF_FAILED(WdfRequestRetrieveInputBuffer(Request, sizeof(ULONG), (PVOID*)&input, nullptr)); + + RETURN_NTSTATUS_IF_FAILED(WdfRequestRetrieveOutputBuffer(Request, 0, (PVOID*)&output, &cbOutputBuffer)); + if (cbOutputBuffer == 0) + { + WdfRequestSetInformation(Request, sizeof(ULONG)); + return STATUS_BUFFER_OVERFLOW; + } + else if (cbOutputBuffer < sizeof(ULONG)) + { + return STATUS_BUFFER_TOO_SMALL; + } + + temp = ~(*input); + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Input received: %x; output being sent back: %x", *input, temp); + + *output = temp; + + WdfRequestSetInformation(Request, sizeof(ULONG)); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +VOID +SdcaXu_EvtIoDeviceControl( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t /*OutputBufferLength*/, + _In_ size_t /*InputBufferLength*/, + _In_ ULONG IoControlCode +) +{ + // The IO Queue for this driver is created with + // attributes.ExecutionLevel = WdfExecutionLevelPassive; + _Analysis_assume_(KeGetCurrentIrql() == PASSIVE_LEVEL); + PAGED_CODE(); + + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; + + switch (IoControlCode) + { + case IOCTL_SDCAVXU_INTERFACE_TEST: + status = SdcaXu_EvtIoctlInterfaceTest(device, Request); + break; + } + + WdfRequestComplete(Request, status); +} + +// +// SdcaXu_ConfigureTestInterface +// +// This function will: +// 1. Add a queue to the given device that will handle the test IOCTL +// 2. Create a device interface so the device can be located through SetupApi methods +// An alternative to using WdfDeviceCreateDeviceInterface would be to use WdfDeviceCreateSymbolicLink +// with a well-formed name +// +PAGED_CODE_SEG +NTSTATUS +SdcaXu_ConfigureTestInterface( + _In_ WDFDEVICE Device, + _In_ PCGUID Interface +) +{ + PAGED_CODE(); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ExecutionLevel = WdfExecutionLevelPassive; + + WDF_IO_QUEUE_CONFIG queueConfig; + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential); + queueConfig.EvtIoDeviceControl = SdcaXu_EvtIoDeviceControl; + + RETURN_NTSTATUS_IF_FAILED(WdfIoQueueCreate(Device, &queueConfig, &attributes, nullptr)); + + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreateDeviceInterface(Device, + Interface, + NULL)); + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuCircuit_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_CIRCUIT_DEVICE_CONTEXT devCtx; + devCtx = GetCircuitDeviceContext(Device); + ASSERT(devCtx != NULL); + + if (!devCtx->FirstTimePrepareHardware) + { + // + // This is a rebalance. Validate the circuit resources and + // if needed, delete and re-create the circuit. + // The sample driver doesn't use resources, thus the existing + // circuits are kept. + // + return STATUS_SUCCESS; + } + + + // + // Set child's power policy. + // + RETURN_NTSTATUS_IF_FAILED(SdcaXuCircuit_SetPowerPolicy(Device)); + + + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateModuleCircuit(Device)); + + // + // Keep track this is not the first time this callback was called. + // + devCtx->FirstTimePrepareHardware = FALSE; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuCircuit_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + + PAGED_CODE(); + + // + // Init the idle policy structure. + // + //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = IDLE_POWER_TIMEOUT; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuCircuit_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_CIRCUIT_DEVICE_CONTEXT devCtx; + devCtx = GetCircuitDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuCircuit_EvtDeviceSelfManagedIoInit( + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + + In this callback, the driver does one-time init of self-managed I/O data. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + PSDCAXU_CIRCUIT_DEVICE_CONTEXT devCtx; + devCtx = GetCircuitDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + return STATUS_SUCCESS; +} + +#pragma code_seg() +VOID +SdcaXuCircuit_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + WDFDEVICE device; + PSDCAXU_CIRCUIT_DEVICE_CONTEXT devCtx; + + device = (WDFDEVICE)WdfDevice; + devCtx = GetCircuitDeviceContext(device); + ASSERT(devCtx != NULL); +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.h new file mode 100644 index 00000000..f537be04 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/CircuitDevice.h @@ -0,0 +1,57 @@ +/*++ + +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: + + CircuitDevice.h + +Abstract: + + Raw PDO for ACX circuits. This file contains routines to create Device + and handle pnp requests + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// +// Circuit's settings for raw PDO. +// +DECLARE_CONST_UNICODE_STRING(CircuitDeviceId, L"SDCAVad\\ExtensionDevice"); +DECLARE_CONST_UNICODE_STRING(CircuitHardwareId, L"SDCAVad\\ExtensionDevice"); +DECLARE_CONST_UNICODE_STRING(CircuitInstanceId, L"00"); +DECLARE_CONST_UNICODE_STRING(CircuitCompatibleId, SDCAVAD_COMPATIBLE_ID); +DECLARE_CONST_UNICODE_STRING(CircuitContainerId, SDCAVAD_CONTAINER_ID); +DECLARE_CONST_UNICODE_STRING(CircuitDeviceDescription, L"SDCAVad Device (Ext)"); +DECLARE_CONST_UNICODE_STRING(CircuitDeviceLocation, L"SDCAVad Device"); + +PAGED_CODE_SEG +NTSTATUS +SDCAVXu_CreateCircuitDevice( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXuCircuit_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +// Render Device callbacks. +EVT_WDF_DEVICE_PREPARE_HARDWARE SdcaXuCircuit_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE SdcaXuCircuit_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT SdcaXuCircuit_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXuCircuit_EvtDeviceContextCleanup; + +#pragma code_seg() + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Device.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Device.h new file mode 100644 index 00000000..eaf6b306 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Device.h @@ -0,0 +1,37 @@ +/*++ + +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: + + render.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// +// Device settings for raw PDO. +// +DECLARE_CONST_UNICODE_STRING(DeviceId, L"SDCAVad\\ExtensionDevice"); +DECLARE_CONST_UNICODE_STRING(HardwareId, L"SDCAVad\\ExtensionDevice"); +DECLARE_CONST_UNICODE_STRING(InstanceId, L"00"); +DECLARE_CONST_UNICODE_STRING(CompatibleId, SDCAVAD_COMPATIBLE_ID); +DECLARE_CONST_UNICODE_STRING(ContainerId, SDCAVAD_CONTAINER_ID); +DECLARE_CONST_UNICODE_STRING(DeviceDescription, L"SDCAVad Extension Device"); +DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"SDCAVad"); + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.cpp new file mode 100644 index 00000000..85926c07 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.cpp @@ -0,0 +1,376 @@ +/*++ + + 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: + + ModuleCircuit.cpp + +Abstract: + + Circuit implementation that hosts an AudioModule + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include "audiomodule.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> + +#include "ModuleCircuit.h" + +#ifndef __INTELLISENSE__ +#include "ModuleCircuit.tmh" +#endif + +DEFINE_GUID(SDCAXU_MODULECIRCUIT_GUID, +0x63434534, 0xBD84, 0x8DFE, 0x7A, 0xAA, 0xFF, 0x84, 0xD8, 0x23, 0xAB, 0xBD); + +DEFINE_GUID(KSCATEGORY_ACXCIRCUIT, +0x2c6bb644L, 0xe1ae, 0x47f8, 0x9a, 0x2b, 0x1d, 0x1f, 0xa7, 0x50, 0xf2, 0xfa); + +DEFINE_GUID(SDCAXU_FACTORY_CATEGORY, +0x1983badd, 0x5cd, 0x4dc8, 0x83, 0xe5, 0x84, 0xaf, 0x83, 0xdf, 0xb0, 0xc3); + +// +// Name of circuit hosting an XU module. +// +DECLARE_CONST_UNICODE_STRING(s_ModuleCircuitName, L"ExtensionModuleCircuit"); + + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtProcessCommand( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + BOOL fNewValue = FALSE; + PVOID currentValue; + PVOID inBuffer = NULL; + ULONG inBufferCb = 0; + PSDCAXU_AUDIOMODULE_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL; + AUDIOMODULE_CUSTOM_COMMAND * command = NULL; + + audioModuleCtx = GetSdcaXuAudioModuleContext(AudioModule); + if (audioModuleCtx == NULL) + { + ASSERT(FALSE); // this should not happen. + status = STATUS_INTERNAL_ERROR; + goto exit; + } + + // + // Basic parameter validation (module specific). + // + if (InBuffer == NULL || InBufferCb == 0) + { + return STATUS_INVALID_PARAMETER; + } + + if (InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND)) + { + return STATUS_INVALID_PARAMETER; + } + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + if (command->ParameterId >= SIZEOF_ARRAY(AudioModule_ParameterInfo)) + { + return STATUS_INVALID_PARAMETER; + } + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule_ParameterInfo[AudioModuleParameter2]; + break; + default: + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = NULL; + } + + status = AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue); + + if (!NT_SUCCESS(status)) + { + goto exit; + } + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + + status = AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification)); + if (!NT_SUCCESS(status)) + { + goto exit; + } + } + + // Normalize error code. + status = STATUS_SUCCESS; + +exit: + return status; +} + + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateModuleCircuitModules( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit + ) +/*++ + +Routine Description: + + This routine creates all of the audio module elements and adds them to the circuit + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + ACX_AUDIOMODULE_CALLBACKS audioModuleCallbacks; + ACX_AUDIOMODULE_CONFIG audioModuleCfg; + ACXAUDIOMODULE audioModuleElement; + PSDCAXU_AUDIOMODULE_CONTEXT audioModuleCtx; + ACX_PNPEVENT_CONFIG audioModuleEventCfg; + ACXPNPEVENT audioModuleEvent; + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModuleId; + audioModuleCfg.Descriptor.ClassId = AudioModuleId; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(0,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE_MINOR; + status = RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULEDESCRIPTION, + wcslen(AUDIOMODULEDESCRIPTION)); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE_CONTEXT); + attributes.ParentObject = Circuit; + + status = AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + audioModuleCtx = GetSdcaXuAudioModuleContext(audioModuleElement); + ASSERT(audioModuleCtx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + status = AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + audioModuleCtx->Event = audioModuleEvent; + + status = AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + // + // Done. + // + status = STATUS_SUCCESS; + +exit: + return status; +} + +_Function_class_(EVT_ACX_CIRCUIT_CREATE_STREAM) +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtAcxCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(StreamInit); + UNREFERENCED_PARAMETER(StreamFormat); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + return STATUS_NOT_SUPPORTED; +} + + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateModuleCircuit( + _In_ WDFDEVICE Device + ) +{ + PAGED_CODE(); + + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + PACXCIRCUIT_INIT circuitInit = NULL; + SDCAXU_MODULECIRCUIT_CONTEXT * circuitCtx; + + // + // ACX expects an 'other' circuit to start with KSCATEGORY_ACXCIRCUIT and also have + // KSCATEGORY_AUDIO. The XU driver can add other categories after these. + // + GUID categories[] = { + KSCATEGORY_ACXCIRCUIT, + KSCATEGORY_AUDIO, + SDCAXU_FACTORY_CATEGORY + }; + + // + // Get a CircuitInit structure. + // + circuitInit = AcxCircuitInitAllocate(Device); + + // + // Add circuit identifiers. + // + AcxCircuitInitSetComponentId(circuitInit, &SDCAXU_MODULECIRCUIT_GUID); + AcxCircuitInitAssignCategories(circuitInit, categories, ARRAYSIZE(categories)); + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeOther); + AcxCircuitInitAssignName(circuitInit, &s_ModuleCircuitName); + AcxCircuitInitAssignAcxCreateStreamCallback(circuitInit, SdcaXu_EvtAcxCircuitCreateStream); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_MODULECIRCUIT_CONTEXT); + attributes.ParentObject = Device; + status = AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + // circuitInit has been freed by AcxCircuitCreate at this point + ASSERT(circuitInit == NULL); + + ASSERT(circuit != NULL); + circuitCtx = GetModuleCircuitContext(circuit); + ASSERT(circuitCtx); + UNREFERENCED_PARAMETER(circuitCtx); + + // + // Create and add the audio modules to the circuit + // + status = SdcaXu_CreateModuleCircuitModules(Device, circuit); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + // + // Add circuit to device. + // + status = AcxDeviceAddCircuit(Device, circuit); + if (!NT_SUCCESS(status)) + { + ASSERT(FALSE); + goto exit; + } + + // Done + status = STATUS_SUCCESS; + +exit: + if (circuitInit) + { + AcxCircuitInitFree(circuitInit); + } + return status; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.h new file mode 100644 index 00000000..17fbfc4d --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/ModuleCircuit.h @@ -0,0 +1,32 @@ +/*++ + +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: + + ModuleCircuit.h + +Abstract: + + Raw PDO for ACX circuits. This file contains routines to create Device + and handle pnp requests + +Environment: + + Kernel mode + +--*/ + +#pragma once + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateModuleCircuit( + _In_ WDFDEVICE Device +); + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.vcxproj b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.vcxproj new file mode 100644 index 00000000..c3cfaadc --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.vcxproj @@ -0,0 +1,355 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <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|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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B1B6FD46-A26E-4D07-BE2E-FD87725500DC}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR> + <ACX_VERSION_MAJOR>1</ACX_VERSION_MAJOR> + <ACX_VERSION_MINOR>0</ACX_VERSION_MINOR> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <SupportsPackaging>false</SupportsPackaging> + <RequiresPackageProject>true</RequiresPackageProject> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies> + </Link> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppAdditionalOptions>-km \ +-DENABLE_WPP_RECORDER=1 \ +-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \ +-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \ +-p:SDCAVCodec</WppAdditionalOptions> + <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inx)" Include="*.inx" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="AudioModule.h" /> + <ClInclude Include="capture.h" /> + <ClInclude Include="CircuitDevice.h" /> + <ClInclude Include="Device.h" /> + <ClInclude Include="driver.h" /> + <ClInclude Include="ModuleCircuit.h" /> + <ClInclude Include="..\inc\NewDelete.h" /> + <ClInclude Include="private.h" /> + <ClInclude Include="render.h" /> + <ClInclude Include="streamengine.h" /> + <ClInclude Include="Trace.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AudioModule.cpp" /> + <ClCompile Include="capture.cpp" /> + <ClCompile Include="CircuitDevice.cpp" /> + <ClCompile Include="device.cpp" /> + <ClCompile Include="driver.cpp" /> + <ClCompile Include="ModuleCircuit.cpp" /> + <ClCompile Include="..\common\NewDelete.cpp" /> + <ClCompile Include="render.cpp" /> + <ClCompile Include="streamengine.cpp" /> + <ResourceCompile Include="resources.rc" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.vcxproj.Filters new file mode 100644 index 00000000..8d058e73 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SDCAVXu.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"> + <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> +</Project> diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SdcaVXu.inx b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SdcaVXu.inx new file mode 100644 index 00000000..28c86344 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/SdcaVXu.inx @@ -0,0 +1,144 @@ +;/*++ +; +;Copyright (c) Microsoft Corporation. All rights reserved. +; +;Module Name: +; +; SDCAVXu.INF +; +;--*/ + +[Version] +Signature="$WINDOWS NT$" +Class=Extension +ClassGuid={e2f84ce7-8efa-411c-aa69-97454ca4cb57} +Provider=%ProviderName% +DriverVer=06/13/2016, 1.0.0.1 +CatalogFile=SDCAVad.cat +ExtensionId={790C1DE0-AA33-4CB8-BB0C-F523C73B4AA1} +PnpLockdown=1 + +[DestinationDirs] +DefaultDestDir = 13 + +;***************************************** +; Audio Device Install Section +;***************************************** +[Manufacturer] +%StdMfg%=Standard,NT$ARCH$.10.0...19041 + +;*************************************************************** +; XU filter is installed as Lower filter to SDCAVCodec +; Match hw-id +;*************************************************************** +[Standard.NT$ARCH$.10.0...19041] +; Replace following with real Hardware Ids +%WdfExtensionDevice.DeviceDesc%=Audio_Device, ROOT\SDCAVCodec +%WdfExtensionDevice.DeviceDesc%=Audio_Device, SOUNDWIRE\AUDIOFUNCTION +%WdfExtensionDevice.DeviceDesc%=Audio_Device, SDCA_10\AUDIOFUNCTION +%WdfExtensionDevice.DeviceDesc%=Audio_Device, SDCA_11\AUDIOFUNCTION + +%WdfExtensionDevice.DeviceDesc%=Audio_APO_Device, SOUNDWIRE\DynamicEnumChild + +[Audio_Device.NT] +CopyFiles=Audio_Device.NT.Copy + +[Audio_Device.NT.Copy] +SDCAVXu.sys + +[Audio_Device.NT.Filters] +AddFilter=SDCAVXu,,SDCAVXuInstall + +[Audio_APO_Device.NT] + +[Audio_APO_Device.NT.HW] +; The FriendlyName_AddReg will change the name of the SdcaClass child device +;AddReg = FriendlyName_AddReg + +;[FriendlyName_AddReg] +;HKR,,FriendlyName,,%ExtendedFriendlyName% + +[Audio_APO_Device.NT.Components] +AddComponent = SdcaVKwsApo,,Apo_AddComponent + +[Apo_AddComponent] +ComponentIDs = VEN_SDCAV_SMPL&CID_APO +Description = "Audio SDCAV APO Sample" + +[SDCAVXuInstall] +FilterLevel=SDCAXu + +[DeviceExtensions.I.Microphone] +AddReg=DeviceExtensions.I.Microphone.AddReg + +[DeviceExtensions.I.Microphone.AddReg] +HKR,FX\0,%PKEY_FX_Association%,,%KSNODETYPE_ANY% +HKR,FX\0,%PKEY_FX_KeywordDetector_ModeEffectClsid%,,%FX_DISCOVER_EFFECTS_APO_CLSID% +HKR,FX\0,%PKEY_FX_KeywordDetector_EndpointEffectClsid%,,%KWS_FX_ENDPOINT_CLSID% + +; An EFX APO must support default mode to be loaded. This does not mean the keyword burst pin must support default mode, it +; may still run in some other mode like speech mode. This simply means that the KWS EFX APO supports default mode. +HKR,FX\0,%PKEY_EFX_KeywordDetector_ProcessingModes_Supported_For_Streaming%,%REG_MULTI_SZ%,%AUDIO_SIGNALPROCESSINGMODE_DEFAULT% + +[Audio_APO_Device.NT.Interfaces] +AddInterface = %KSCATEGORY_AUDIO%, %KSNAME_Microphone%, DeviceExtensions.I.Microphone +AddInterface = %KSCATEGORY_CAPTURE%, %KSNAME_Microphone%, DeviceExtensions.I.Microphone +AddInterface = %KSCATEGORY_REALTIME%, %KSNAME_Microphone%, DeviceExtensions.I.Microphone + + +;-------------- Service installation + +[Audio_Device.NT.Services] +AddService = SDCAVXu,,Audio_Service_Inst + +[Audio_Service_Inst] +DisplayName = %WdfExtensionDevice.DeviceDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %13%\SDCAVXu.sys + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +SDCAVXu.sys = 1,, + +[Audio_Device.NT.Wdf] +KmdfService = SDCAVXu, Audio_wdfsect +[Audio_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + +[Strings] + +ProviderName = "VS_Microsoft" + +; +;Localizable +; +StdMfg = "SDCA Virtual XU Audio Device" +DiskId1 = "SDCA Virtual XU Audio Driver Installation Disk" +WdfExtensionDevice.DeviceDesc = "SDCA Virtual XU Audio Driver" + +ExtendedFriendlyName = "SDCAV (with APO Extensions)" +PKEY_FX_Association = "{D04E05A6-594B-4FB6-A80D-01AF5EED7D1D},0" +PKEY_FX_KeywordDetector_EndpointEffectClsid = "{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},10" +PKEY_FX_KeywordDetector_ModeEffectClsid = "{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},9" +PKEY_EFX_KeywordDetector_ProcessingModes_Supported_For_Streaming = "{D3993A3F-99C2-4402-B5EC-A92A0367664B},10" + +FX_DISCOVER_EFFECTS_APO_CLSID = "{CABC2F7B-4AF5-47F8-A95D-3A6F23F53DD4}" + +KWS_FX_ENDPOINT_CLSID = "{9D89F614-F9D6-40DD-9F21-5E69FA3981ED}" + +KSNODETYPE_ANY = "{00000000-0000-0000-0000-000000000000}" + +KSNAME_Microphone="Microphone0" + +KSCATEGORY_AUDIO = "{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_REALTIME = "{EB115FFC-10C8-4964-831D-6DCB02E6F23F}" +KSCATEGORY_CAPTURE = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}" + +REG_MULTI_SZ = 0x00010000 ; FLG_ADDREG_TYPE_MULTI_SZ + +AUDIO_SIGNALPROCESSINGMODE_DEFAULT = "{C18E2F7E-933D-4965-B7D1-1EEF228D2AF3}" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Trace.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Trace.h new file mode 100644 index 00000000..245248a7 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/Trace.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + +Trace.h + +--*/ + +#pragma once + +#include <WppRecorder.h> +#include <evntrace.h> // For TRACE_LEVEL definitions + +#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) +#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4) + +// {47BE3522-EAE5-47F4-9EE0-BC4260C39937} +#define WPP_CONTROL_GUIDS \ +WPP_DEFINE_CONTROL_GUID(DrvLogger,(47BE3522,EAE5,47F4,9EE0,BC4260C39937), \ + WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \ + ) + +#include "trace_macros.h" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.cpp new file mode 100644 index 00000000..150336b1 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.cpp @@ -0,0 +1,1059 @@ +/*++ + + 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: + + Capture.cpp + +Abstract: + + Plug and Play module. This file contains routines to handle pnp requests. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> + +#include "capture.h" + +#include "streamengine.h" + +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "capture.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_EvtAcxPinSetDataFormat ( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +#pragma code_seg() +VOID +SdcaXuC_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin + ) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +VOID SdcaXuC_EvtCircuitContextCleanup(_In_ WDFOBJECT Object) +{ + ACXCIRCUIT circuit = (ACXCIRCUIT)Object; + PSDCAXU_CAPTURE_CIRCUIT_CONTEXT cirCtx = GetCaptureCircuitContext(circuit); + + if (cirCtx->CircuitConfig) + { + ExFreePoolWithTag(cirCtx->CircuitConfig, DRIVER_TAG); + cirCtx->CircuitConfig = NULL; + } + + return; +} + +PAGED_CODE_SEG +VOID +SdcaXuC_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +VOID +SdcaXuC_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request +) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + + PAGED_CODE(); + + // + // Init the idle policy structure. + // + //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = IDLE_POWER_TIMEOUT; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + if (!devCtx->FirstTimePrepareHardware) + { + // + // This is a rebalance. Validate the circuit resources and + // if needed, delete and re-create the circuit. + // The sample driver doens't use resources, thus the existing + // circuits are kept. + // + return STATUS_SUCCESS; + } + + // + // Set child's power policy. + // + RETURN_NTSTATUS_IF_FAILED(SdcaXuC_SetPowerPolicy(Device)); + + // + // Add circuit to child's list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Circuit)); + + // + // Keep track this is not the first time this callback was called. + // + devCtx->FirstTimePrepareHardware = FALSE; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + + return status; +} + +PAGED_CODE_SEG +VOID +SdcaXuC_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up capture device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(WdfDevice); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_EvtDeviceSelfManagedIoInit( + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + + In this callback, the driver does one-time init of self-managed I/O data. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + PSDCAXU_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateCaptureDevice( + _In_ WDFDEVICE Device, + _Out_ WDFDEVICE* CaptureDevice +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE captureDevice = NULL; + + PAGED_CODE(); + + auto exit = scope_exit([&status, &captureDevice]() { + if (!NT_SUCCESS(status)) + { + if (captureDevice != NULL) + { + WdfObjectDelete(captureDevice); + } + } + }); + + *CaptureDevice = NULL; + + // + // Create a child audio device for this circuit. + // + PWDFDEVICE_INIT devInit = NULL; + devInit = WdfPdoInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == devInit, STATUS_MEMORY_NOT_ALLOCATED); + + auto devInit_free = scope_exit([&devInit, &status]() { + WdfDeviceInitFree(devInit); + }); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &CaptureHardwareId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(devInit, &CaptureDeviceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddCompatibleID(devInit, &CaptureCompatibleId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(devInit, &CaptureInstanceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignContainerID(devInit, &CaptureContainerId)); + + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(devInit, + &CaptureDeviceDescription, + &CaptureDeviceLocation, + 0x409)); + + WdfPdoInitSetDefaultLocale(devInit, 0x409); + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG acxDevInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&acxDevInitCfg); + acxDevInitCfg.Flags |= AcxDeviceInitConfigRawDevice; + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(devInit, &acxDevInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = SdcaXuC_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = SdcaXuC_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = SdcaXuC_EvtDeviceSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(devInit, &pnpPowerCallbacks); + + // + // Specify a context for this capture device. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_CAPTURE_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuC_EvtDeviceContextCleanup; + attributes.ExecutionLevel = WdfExecutionLevelPassive; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&devInit, &attributes, &captureDevice)); + + // + // devInit attached to device, no need to free + // + devInit_free.release(); + + // + // Tell the framework to set the NoDisplayInUI in the DeviceCaps so + // that the device does not show up in Device Manager. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.NoDisplayInUI = WdfTrue; + WdfDeviceSetPnpCapabilities(captureDevice, &pnpCaps); + + // + // Init capture's device context. + // + PSDCAXU_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(captureDevice); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(captureDevice, &devCfg)); + + // + // Set output value. + // + *CaptureDevice = captureDevice; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddDynamicCapture( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Create a device to associated with this circuit. + // + WDFDEVICE captureDevice = NULL; + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateCaptureDevice(Device, &captureDevice)); + auto deviceFree = scope_exit([&captureDevice]() { + WdfObjectDelete(captureDevice); + }); + + ASSERT(captureDevice); + PSDCAXU_CAPTURE_DEVICE_CONTEXT captureDevCtx; + captureDevCtx = GetCaptureDeviceContext(captureDevice); + ASSERT(captureDevCtx); + + // + // Create a capture circuit associated with this child device. + // + ACXCIRCUIT captureCircuit = NULL; + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateCaptureCircuit(captureDevice, CircuitConfig, &captureCircuit)); + + captureDevCtx->Circuit = captureCircuit; + captureDevCtx->FirstTimePrepareHardware = TRUE; + + // + // Add circuit to device's dynamic circuit device list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuitDevice(Device, captureDevice)); + + // Successfully created circuit for dynamic deivce + // Do not delete + deviceFree.release(); + + PSDCAXU_DEVICE_CONTEXT devCtx = GetSdcaXuDeviceContext(Device); + for (ULONG i = 0; i < ARRAYSIZE(devCtx->EndpointDevices); ++i) + { + if (devCtx->EndpointDevices[i].CircuitDevice == nullptr) + { + DrvLogInfo(g_SDCAVXuLog, FLAG_DDI, L"XU Device %p adding capture circuit device %p with component ID %!GUID! Uri %ls", + Device, captureDevice, &CircuitConfig->ComponentID, + CircuitConfig->ComponentUri.Buffer ? CircuitConfig->ComponentUri.Buffer : L"<none>"); + devCtx->EndpointDevices[i].CircuitDevice = captureDevice; + devCtx->EndpointDevices[i].CircuitId = CircuitConfig->ComponentID; + if (CircuitConfig->ComponentUri.Length > 0) + { + USHORT cbAlloc = CircuitConfig->ComponentUri.Length + sizeof(WCHAR); + // protect against overflow + if (CircuitConfig->ComponentUri.Length % 2 != 0 || + cbAlloc < CircuitConfig->ComponentUri.Length) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INVALID_PARAMETER); + } + + PWCHAR circuitUri = (PWCHAR)ExAllocatePool2(POOL_FLAG_NON_PAGED, cbAlloc, DRIVER_TAG); + if (!circuitUri) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INSUFFICIENT_RESOURCES); + } + + devCtx->EndpointDevices[i].CircuitUri.Buffer = circuitUri; + devCtx->EndpointDevices[i].CircuitUri.MaximumLength = cbAlloc; + devCtx->EndpointDevices[i].CircuitUri.Length = 0; + RtlCopyUnicodeString(&devCtx->EndpointDevices[i].CircuitUri, &CircuitConfig->ComponentUri); + } + break; + } + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig, + _Out_ ACXCIRCUIT *Circuit +) +/*++ + +Routine Description: + + This routine builds the SdcaXu capture circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Get a CircuitInit structure. + // + PACXCIRCUIT_INIT circuitInit = NULL; + circuitInit = AcxCircuitInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_MEMORY_NOT_ALLOCATED); + auto circuitInit_free = scope_exit([&circuitInit]() { + AcxCircuitInitFree(circuitInit); + }); + + // + // Init output value. + // + *Circuit = NULL; + + // + // Copy Circuit configuration + // + PSDCAXU_ACX_CIRCUIT_CONFIG pCircuitConfig = NULL; + pCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2(POOL_FLAG_NON_PAGED, + CircuitConfig->cbSize, + DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == pCircuitConfig, STATUS_MEMORY_NOT_ALLOCATED); + auto circuitConfig_free = scope_exit([&pCircuitConfig]() { + ExFreePoolWithTag(pCircuitConfig, DRIVER_TAG); + }); + + RtlCopyMemory(pCircuitConfig, CircuitConfig, CircuitConfig->cbSize); + + // Remap UNICODE_STRING.Buffer + // buffer for unicode string begins immediately after SdcaXuAcxCircuitConfig + RETURN_NTSTATUS_IF_TRUE_MSG(pCircuitConfig->cbSize < (sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + pCircuitConfig->CircuitName.MaximumLength), + STATUS_INVALID_PARAMETER, L"CircuitConfig->cbSize = %d Required = %d", + pCircuitConfig->cbSize, + (int)(sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + pCircuitConfig->CircuitName.MaximumLength)); + + pCircuitConfig->CircuitName.Buffer = (PWCH)(pCircuitConfig + 1); + + // + // Create a circuit. + // + + // + // Add circuit identifiers. + // + if (!IsEqualGUID(pCircuitConfig->ComponentID, GUID_NULL)) + { + AcxCircuitInitSetComponentId(circuitInit, &pCircuitConfig->ComponentID); + } + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &pCircuitConfig->ComponentUri)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(circuitInit, &pCircuitConfig->CircuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeCapture); + + // + // Assign the circuit's pnp-power callbacks. + // + { + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = SdcaXuC_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = SdcaXuC_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + } + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + circuitInit, + SdcaXuC_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + circuitInit, + SdcaXuC_EvtCircuitCreateStream)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit, + CircuitProperties, + CircuitPropertiesCount)); + */ + + // + // Disable default Stream Bridge handling in ACX + // Create stream handler will add Stream Bridge + // to support Object-bag forwarding + // + AcxCircuitInitDisableDefaultStreamBridgeHandling(circuitInit); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_CAPTURE_CIRCUIT_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuC_EvtCircuitContextCleanup; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + // circuitInit is now associated with circuit and will be managed with + // circuit lifetime. + circuitInit_free.release(); + + SDCAXU_CAPTURE_CIRCUIT_CONTEXT* circuitCtx; + ASSERT(circuit != NULL); + circuitCtx = GetCaptureCircuitContext(circuit); + ASSERT(circuitCtx); + + circuitCtx->CircuitConfig = pCircuitConfig; + circuitConfig_free.release(); + + // + // Post circuit creation initialization. + // + + // + // Add two custom circuit elements. Note that driver doesn't need to + // perform this step if it doesn't want to expose any circuit elements. + // + + // + // Create 1st custom circuit-element. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + const int numElements = 2; + ACXELEMENT elements[numElements] = { 0 }; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + SDCAXU_ELEMENT_CONTEXT* elementCtx; + elementCtx = GetSdcaXuElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom circuit-element. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetSdcaXuElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add the circuit elements + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + + // + // Create capture pin. AcxCircuit creates the other pin by default. + // + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = SdcaXuC_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG pinCfg; + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PIN_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuC_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + ACXPIN pin; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + SDCAXU_PIN_CONTEXT* pinCtx; + pinCtx = GetSdcaXuPinContext(pin); + ASSERT(pinCtx); + + // When the downstream pin connects to the Class driver, we'll + // copy formats from the Class driver (instead of hardcoding + // formats here) + + // + // Add capture pin, using default pin id (0) + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create bridge pin. AcxCircuit creates the other pin by default. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinConnected = SdcaXu_EvtPinConnected; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PIN_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuC_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + pin = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + pinCtx = GetSdcaXuPinContext(pin); + ASSERT(pinCtx); + + // + // Add brige pin, using default pin id (1) + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + // + // Add a stream bridge to the bridge pin to propagate the stream obj-bags. + // + { + PCGUID inModes[] = + { + &NULL_GUID, // Match every mode. + }; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = pin; + + ACX_STREAM_BRIDGE_CONFIG streamBridgeConfig; + ACX_STREAM_BRIDGE_CONFIG_INIT(&streamBridgeConfig); + + streamBridgeConfig.Flags |= AcxStreamBridgeForwardInStreamVarArguments; + streamBridgeConfig.InModesCount = ARRAYSIZE(inModes); + streamBridgeConfig.InModes = inModes; + streamBridgeConfig.OutMode = &NULL_GUID; // Use the MODE associated the in-stream. + + ACXSTREAMBRIDGE streamBridge = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeCreate(circuit, &attributes, &streamBridgeConfig, &streamBridge)); + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddStreamBridges(pin, &streamBridge, 1)); + } + + // + // Explicitly connect the circuit/elements. Note that driver doens't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both capture and capture devices. + // + // circuit.pin[default_sink] -> 1st element.pin[default_in] + // 1st element.pin[default_out] -> 2nd element.pin[default_in] + // 2nd element.pin[default_out] -> circuit.pin[default_source] + // + const int numConnections = numElements + 1; + ACX_CONNECTION connections[numConnections]; + ACX_CONNECTION_INIT(&connections[0], circuit, elements[0]); + ACX_CONNECTION_INIT(&connections[1], elements[0], elements[1]); + ACX_CONNECTION_INIT(&connections[2], elements[1], circuit); + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(circuit, connections, SIZEOF_ARRAY(connections))); + + // + // Set output value. + // + *Circuit = circuit; + + // + // Done. + // + + return status; +} + +#pragma code_seg() +_Use_decl_annotations_ +NTSTATUS +SdcaXuC_EvtCircuitPowerUp ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState + ) +{ + // Do not page out. + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +NTSTATUS +SdcaXuC_EvtCircuitPowerDown ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments + ) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + PSDCAXU_CAPTURE_DEVICE_CONTEXT devCtx; + devCtx = GetCaptureDeviceContext(Device); + ASSERT(devCtx != NULL); + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + SdcaXuC_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = SdcaXu_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = SdcaXu_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = SdcaXu_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = SdcaXu_EvtStreamPause; + streamCallbacks.EvtAcxStreamAssignDrmContentId = SdcaXu_EvtStreamAssignDrmContentId; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_STREAM_CONTEXT); + attributes.EvtDestroyCallback = SdcaXu_EvtStreamDestroy; + ACXSTREAM stream; + RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + CCaptureStreamEngine *streamEngine = NULL; + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CCaptureStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_MEMORY_NOT_ALLOCATED); + auto stream_scope = scope_exit([&streamEngine]() { + delete streamEngine; + }); + + SDCAXU_STREAM_CONTEXT *streamCtx; + streamCtx = GetSdcaXuStreamContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)streamEngine; + stream_scope.release(); + + // + // Post stream creation initialization. + // + + ACXELEMENT elements[2] = {0}; + ACX_ELEMENT_CONFIG elementCfg; + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + SDCAXU_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetSdcaXuElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetSdcaXuElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + // + // Done. + // + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddCaptures( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Add dynamic capture circuit using raw PDO + // + status = SdcaXu_AddDynamicCapture(Device, CircuitConfig); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.h new file mode 100644 index 00000000..16f3218d --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/capture.h @@ -0,0 +1,84 @@ +/*++ + +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: + + capture.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// +// Circuit's settings for raw PDO. +// +DECLARE_CONST_UNICODE_STRING(CaptureDeviceId, L"SDCAVad\\ExtensionMicrophone"); +DECLARE_CONST_UNICODE_STRING(CaptureHardwareId, L"SDCAVad\\ExtensionMicrophone"); +DECLARE_CONST_UNICODE_STRING(CaptureInstanceId, L"00"); +DECLARE_CONST_UNICODE_STRING(CaptureCompatibleId, SDCAVAD_COMPATIBLE_ID); +DECLARE_CONST_UNICODE_STRING(CaptureContainerId, SDCAVAD_CONTAINER_ID); +DECLARE_CONST_UNICODE_STRING(CaptureDeviceDescription, L"SDCAVad Microphone(Ext)"); +DECLARE_CONST_UNICODE_STRING(CaptureDeviceLocation, L"SDCAVad Microphone"); + +PAGED_CODE_SEG +NTSTATUS +SdcaXuC_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateCaptureDevice( + _In_ WDFDEVICE Device, + _Out_ WDFDEVICE *CaptureDevice +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddDynamicCapture( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateCaptureCircuit( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig, + _Out_ ACXCIRCUIT *Circuit +); + +// Capture Device callbacks. + +EVT_WDF_DEVICE_PREPARE_HARDWARE SdcaXuC_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE SdcaXuC_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT SdcaXuC_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXuC_EvtDeviceContextCleanup; + +// Capture callbacks. + +EVT_WDF_OBJECT_CONTEXT_CLEANUP SdcaXuC_EvtCircuitContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST SdcaXuC_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM SdcaXuC_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP SdcaXuC_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN SdcaXuC_EvtCircuitPowerDown; +EVT_ACX_PIN_SET_DATAFORMAT SdcaXuC_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXuC_EvtPinContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST SdcaXuC_EvtStreamRequestPreprocess; + +#pragma code_seg() + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/device.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/device.cpp new file mode 100644 index 00000000..766e6b8c --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/device.cpp @@ -0,0 +1,1426 @@ +/*++ + + 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: + + Device.cpp + +Abstract: + + Plug and Play module. This file contains routines to handle pnp requests. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> + +#include "streamengine.h" +#include "device.h" +#include "CircuitDevice.h" +#include "ModuleCircuit.h" + +#include "AudioFormats.h" + +#ifndef __INTELLISENSE__ +#include "device.tmh" +#endif + +UNICODE_STRING g_RegistryPath = {0}; // This is used to store the registry settings path for the driver + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +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 + +--*/ + +{ + PAGED_CODE(); + + // 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, DRIVER_TAG); + + if (g_RegistryPath.Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // ExAllocatePool2 zeros memory. + + RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetHwConfig +( + _In_ PVOID Context, + _In_ SDCAXU_HW_CONFIG_TYPE HwConfigType, + _In_opt_ PVOID HwConfigData, + _In_ ULONG HwConfigDataSize +) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext((WDFDEVICE)Context); + + if (HwConfigType == SdcaXuHwConfigTypeAcpiBlob && + NULL != HwConfigData && + sizeof(devCtx->SDCADeviceData.HwData) <= HwConfigDataSize) + { + RtlCopyMemory(&devCtx->SDCADeviceData.HwData, HwConfigData, sizeof(devCtx->SDCADeviceData.HwData)); + } + else if (HwConfigType == SdcaXuHwConfigTypeAcpiBlob && + NULL != HwConfigData && + sizeof(SdcaXuAcpiBlob) <= HwConfigDataSize) + { + devCtx->SDCADeviceData.NumEndpoints = ((PSdcaXuAcpiBlob)HwConfigData)->NumEndpoints; + } + + RETURN_NTSTATUS_IF_FAILED(SdcaXu_SetXUEntities((WDFDEVICE)Context)); + + RETURN_NTSTATUS_IF_FAILED(SdcaXu_RegisterForInterrupts((WDFDEVICE)Context)); + + RETURN_NTSTATUS_IF_FAILED(SdcaXu_SetJackOverride((WDFDEVICE)Context)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetXUEntities(_In_ WDFDEVICE Device) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(Device); + + if (devCtx->SDCADeviceData.bSDCAInterface) + { + ULONG xuEntities[ARRAYSIZE(devCtx->SDCADeviceData.HwData.AvailableXUEntities)] = { 0 }; + ULONG xuCount = 0; + + // A real driver would select the XU Entites to turn on + //for (ULONG i = 0; i < ARRAYSIZE(devCtx->SDCADeviceData.HwData.AvailableXUEntities); ++i) + //{ + // if (devCtx->SDCADeviceData.HwData.AvailableXUEntities[i] != 0) + // { + // xuEntities[xuCount] = devCtx->SDCADeviceData.HwData.AvailableXUEntities[i]; + // ++xuCount; + // } + //} + + RETURN_NTSTATUS_IF_FAILED(devCtx->SDCADeviceData.SDCAInterface.EvtSetXUEntities(devCtx->SDCADeviceData.SDCAContext, xuCount, xuEntities)); + DrvLogInfo(g_SDCAVXuLog, FLAG_INIT, "SdcaXu_SetXUEntities - Configured %d XU Entities", xuCount); + } + else + { + DrvLogInfo(g_SDCAVXuLog, FLAG_INIT, "SdcaXu_SetXUEntities - No SDCA Interface available"); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_RegisterForInterrupts(_In_ WDFDEVICE Device) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(Device); + + if (devCtx->SDCADeviceData.bSDCAInterface) + { + + SDCAXU_INTERRUPT_INFO interruptInfo{ 0 }; + + interruptInfo.Size = sizeof(SDCAXU_INTERRUPT_INFO); + SDCA_INTERRUPT_DEFINE_MASK(interruptInfo.SDCAInterruptMask, 0); + //SDCA_INTERRUPT_DEFINE_MASK(interruptInfo.SCPInterruptMask, 1, 2); + //SDCA_INTERRUPT_DEFINE_MASK(interruptInfo.DataPortInterrupts[0], 1, 2); + //SDCA_INTERRUPT_DEFINE_MASK(interruptInfo.DataPortInterrupts[1], 1, 5); + + RETURN_NTSTATUS_IF_FAILED(devCtx->SDCADeviceData.SDCAInterface.EvtRegisterForInterrupts( + devCtx->SDCADeviceData.SDCAContext, + &interruptInfo)); + + DrvLogInfo(g_SDCAVXuLog, FLAG_INIT, "SdcaXu_RegisterForInterrupts - Registered for Interrupts"); + } + else + { + RETURN_NTSTATUS(STATUS_NOINTERFACE); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetJackOverride(_In_ WDFDEVICE Device) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(Device); + + if (devCtx->SDCADeviceData.bSDCAInterface) + { + //RETURN_NTSTATUS_IF_FAILED(devCtx->SDCADeviceData.SDCAInterface.EvtSetJackOverride( + // devCtx->SDCADeviceData.SDCAContext, + // TRUE)); + + DrvLogInfo(g_SDCAVXuLog, FLAG_INIT, "SdcaXu_SetJackOverride - Skipping enabling Jack Override"); + } + else + { + RETURN_NTSTATUS(STATUS_NOINTERFACE); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetEndpointConfig +( + _In_ PVOID Context, + _In_ SDCAXU_ENDPOINT_CONFIG_TYPE EndpointConfigType, + _In_opt_ PVOID EndpointConfigData, + _In_ ULONG EndpointConfigDataSize +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + RETURN_NTSTATUS_IF_TRUE(NULL == EndpointConfigData, STATUS_INVALID_PARAMETER); + + WDFDEVICE Device = (WDFDEVICE)Context; + + switch (EndpointConfigType) + { + case SdcaXuEndpointConfigTypeAcxCircuitConfig: + { + RETURN_NTSTATUS_IF_TRUE_MSG((sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) > EndpointConfigDataSize || + sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) > ((PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData)->cbSize), + STATUS_INVALID_PARAMETER_1, L"%d %d", EndpointConfigDataSize, ((PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData)->cbSize); + + PSDCAXU_ACX_CIRCUIT_CONFIG circuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData; + // + // Add Xu circuit. + // + if (AcxCircuitTypeRender == circuitConfig->CircuitType) + { + RETURN_NTSTATUS_IF_FAILED_MSG(SdcaXu_AddRenders(Device, circuitConfig), L"Device %p", Device); + } + else if (AcxCircuitTypeCapture == circuitConfig->CircuitType) + { + RETURN_NTSTATUS_IF_FAILED_MSG(SdcaXu_AddCaptures(Device, circuitConfig), L"Device %p", Device); + } + } + break; + + default: + RETURN_NTSTATUS_MSG(STATUS_INVALID_PARAMETER_2, L"%d", EndpointConfigType); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_RemoveEndpointConfig +( + _In_ PVOID Context, + _In_ SDCAXU_ENDPOINT_CONFIG_TYPE EndpointConfigType, + _In_opt_ PVOID EndpointConfigData, + _In_ ULONG EndpointConfigDataSize +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogEnter(g_SDCAVXuLog); + + RETURN_NTSTATUS_IF_TRUE(NULL == EndpointConfigData, STATUS_INVALID_PARAMETER); + + WDFDEVICE Device = (WDFDEVICE)Context; + + switch (EndpointConfigType) + { + case SdcaXuEndpointConfigTypeAcxCircuitConfig: + { + RETURN_NTSTATUS_IF_TRUE_MSG((sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) > EndpointConfigDataSize || + sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) > ((PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData)->cbSize), + STATUS_INVALID_PARAMETER_1, L"%d %d", EndpointConfigDataSize, ((PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData)->cbSize); + + PSDCAXU_ACX_CIRCUIT_CONFIG circuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)EndpointConfigData; + + PSDCAXU_DEVICE_CONTEXT devCtx = GetSdcaXuDeviceContext(Device); + for (ULONG i = 0; i < ARRAYSIZE(devCtx->EndpointDevices); ++i) + { + if (circuitConfig->ComponentUri.Length > 0) + { + if (devCtx->EndpointDevices[i].CircuitUri.Buffer && + RtlEqualUnicodeString(&circuitConfig->ComponentUri, &devCtx->EndpointDevices[i].CircuitUri, TRUE /* case insensitive */)) + { + DrvLogInfo(g_SDCAVXuLog, FLAG_DDI, L"Xu Device %p removing circuit device %p with component URI %ls", + Device, devCtx->EndpointDevices[i].CircuitDevice, circuitConfig->ComponentUri.Buffer); + AcxDeviceRemoveCircuitDevice(Device, devCtx->EndpointDevices[i].CircuitDevice); + ExFreePool(devCtx->EndpointDevices[i].CircuitUri.Buffer); + RtlZeroMemory(&devCtx->EndpointDevices[i], sizeof(ENDPOINT_DEVICE_PAIR)); + break; + } + } + else if (IsEqualGUID(devCtx->EndpointDevices[i].CircuitId, circuitConfig->ComponentID)) + { + DrvLogInfo(g_SDCAVXuLog, FLAG_DDI, L"Xu Device %p removing circuit device %p with component ID %!GUID!", + Device, devCtx->EndpointDevices[i].CircuitDevice, &circuitConfig->ComponentID); + AcxDeviceRemoveCircuitDevice(Device, devCtx->EndpointDevices[i].CircuitDevice); + if (devCtx->EndpointDevices[i].CircuitUri.Buffer) + { + ExFreePool(devCtx->EndpointDevices[i].CircuitUri.Buffer); + } + RtlZeroMemory(&devCtx->EndpointDevices[i], sizeof(ENDPOINT_DEVICE_PAIR)); + break; + } + } + } + break; + + default: + RETURN_NTSTATUS_MSG(STATUS_INVALID_PARAMETER_2, L"%d", EndpointConfigType); + } + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_InterruptHandler +( + _In_ PVOID Context, + _Inout_ PSDCAXU_INTERRUPT_INFO Interrupt +) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Interrupt SCP %08x " + L"DP %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " + L"SDCA %08x", + Device, + Interrupt->SCPInterruptMask, + Interrupt->DataPortInterrupts[0], + Interrupt->DataPortInterrupts[1], + Interrupt->DataPortInterrupts[2], + Interrupt->DataPortInterrupts[3], + Interrupt->DataPortInterrupts[4], + Interrupt->DataPortInterrupts[5], + Interrupt->DataPortInterrupts[6], + Interrupt->DataPortInterrupts[7], + Interrupt->DataPortInterrupts[8], + Interrupt->DataPortInterrupts[9], + Interrupt->DataPortInterrupts[10], + Interrupt->DataPortInterrupts[11], + Interrupt->DataPortInterrupts[12], + Interrupt->DataPortInterrupts[13], + Interrupt->DataPortInterrupts[14], + Interrupt->SDCAInterruptMask); + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuPowerStateChangeHandlerPre(_In_ PVOID Context, _In_ ULONG PDE_EntityId, _In_ SDCAXU_POWER_STATE OldState, _In_ SDCAXU_POWER_STATE NewState) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Power State Change Pre for Entity 0x%x, Current State %d, New State %d", + Device, + PDE_EntityId, + OldState, + NewState); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuPowerStateChangeHandlerPost(_In_ PVOID Context, _In_ ULONG PDE_EntityId, _In_ SDCAXU_POWER_STATE OldState, _In_ SDCAXU_POWER_STATE NewState) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Power State Change Post for Entity 0x%x, Previous State %d, New State %d", + Device, + PDE_EntityId, + OldState, + NewState); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuJackStateChangeHandler(_In_ PVOID Context, _In_ ULONG GroupEntityId, _In_ ULONG DetectedMode, _In_ SDCAXU_JACK_EVENT JackEvent) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + PSDCAXU_DEVICE_CONTEXT devCtx = GetSdcaXuDeviceContext(Device); + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Jack State Change for Entity 0x%x, Detected Mode %d, Event %d, will use %d as Selected Mode", + Device, + GroupEntityId, + DetectedMode, + JackEvent, + DetectedMode); + + // A real XU driver would probably do more with this. + status = devCtx->SDCADeviceData.SDCAInterface.EvtSetJackSelectedMode( + devCtx->SDCADeviceData.SDCAContext, + GroupEntityId, + DetectedMode); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuFunctionHasBeenResetHandler(_In_ PVOID Context) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Device %p Handling Function_Has_Been_Reset", Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuFunctionNeedsInitializationHandler(_In_ PVOID Context) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Device %p Handling Function_Needs_Initialization", Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuFunctionFaultHandler(_In_ PVOID Context) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Device %p Handling Function_Fault", Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuUMPSequenceFaultHandler(_In_ PVOID Context) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Device %p Handling Function_UMP_Sequence_Fault", Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuStreamingStoppedAbnormallyHandler(_In_ PVOID Context) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, L"Device %p Handling Streaming_Stopped_Abnormally", Device); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuCommitGroupHandler(_In_ PVOID Context, _In_ PSDCAXU_NOTIFICATION_COMMIT_GROUP CommitGroup) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Commit Group notification with Commit Group %#x", + Device, + CommitGroup->CommitGroupHandle); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuPostureHandler(_In_ PVOID Context, _In_ PSDCAXU_NOTIFICATION_POSTURE Posture) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling Posture notification with Posture %d", + Device, + Posture->Posture); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuFdlBeginHandler(_In_ PVOID Context, _In_ PSDCAXU_NOTIFICATION_FDL_BEGIN FdlBegin) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling FDL Begin notification for entity %#x", + Device, + FdlBegin->FdlEntityId); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXuFdlEndHandler(_In_ PVOID Context, _In_ PSDCAXU_NOTIFICATION_FDL_END FdlEnd) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + + WDFDEVICE Device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling FDL End notification for entity %#x with status %!STATUS!", + Device, + FdlEnd->FdlEntityId, + FdlEnd->FdlStatus); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS SdcaXu_ChangeNotification( + _In_ PVOID Context, + _In_ SDCAXU_NOTIFICATION_TYPE NotificationType, + _In_opt_ PVOID NotificationData, + _In_ ULONG NotificationDataSize +) +{ + PAGED_CODE(); + + switch (NotificationType) + { + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeJackDetect: + if (sizeof(SDCAXU_NOTIFICATION_JACK_DETECT) <= NotificationDataSize) + { + PSDCAXU_NOTIFICATION_JACK_DETECT pJackNotification = PSDCAXU_NOTIFICATION_JACK_DETECT(NotificationData); + return SdcaXuJackStateChangeHandler(Context, pJackNotification->GroupEntityId, pJackNotification->DetectedMode, pJackNotification->JackEvent); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypePowerPre: + if (sizeof(SDCAXU_NOTIFICATION_POWER) <= NotificationDataSize) + { + PSDCAXU_NOTIFICATION_POWER pPowerNotification = PSDCAXU_NOTIFICATION_POWER(NotificationData); + return SdcaXuPowerStateChangeHandlerPre(Context, pPowerNotification->PowerDomainEntityId, pPowerNotification->OldState, pPowerNotification->NewState); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypePowerPost: + if (sizeof(SDCAXU_NOTIFICATION_POWER) <= NotificationDataSize) + { + PSDCAXU_NOTIFICATION_POWER pPowerNotification = PSDCAXU_NOTIFICATION_POWER(NotificationData); + return SdcaXuPowerStateChangeHandlerPost(Context, pPowerNotification->PowerDomainEntityId, pPowerNotification->OldState, pPowerNotification->NewState); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeHardwareReset: + if (0 == NotificationDataSize) + { + return SdcaXuFunctionHasBeenResetHandler(Context); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeFunctionNeedsInitialization: + if (0 == NotificationDataSize) + { + return SdcaXuFunctionNeedsInitializationHandler(Context); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeFunctionFault: + if (0 == NotificationDataSize) + { + return SdcaXuFunctionFaultHandler(Context); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeUMPSequenceFault: + if (0 == NotificationDataSize) + { + return SdcaXuUMPSequenceFaultHandler(Context); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeStreamingStoppedAbnormally: + if (0 == NotificationDataSize) + { + return SdcaXuStreamingStoppedAbnormallyHandler(Context); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeCommitGroup: + if (sizeof(SDCAXU_NOTIFICATION_COMMIT_GROUP) <= NotificationDataSize) + { + return SdcaXuCommitGroupHandler(Context, (PSDCAXU_NOTIFICATION_COMMIT_GROUP)NotificationData); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypePosture: + if (sizeof(SDCAXU_NOTIFICATION_POSTURE) <= NotificationDataSize) + { + return SdcaXuPostureHandler(Context, (PSDCAXU_NOTIFICATION_POSTURE)NotificationData); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeFdlBegin: + if (sizeof(SDCAXU_NOTIFICATION_FDL_BEGIN) <= NotificationDataSize) + { + return SdcaXuFdlBeginHandler(Context, (PSDCAXU_NOTIFICATION_FDL_BEGIN)NotificationData); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + case SDCAXU_NOTIFICATION_TYPE::SdcaXuNotificationTypeFdlEnd: + if (sizeof(SDCAXU_NOTIFICATION_FDL_END) <= NotificationDataSize) + { + return SdcaXuFdlEndHandler(Context, (PSDCAXU_NOTIFICATION_FDL_END)NotificationData); + } + else + { + return STATUS_INVALID_PARAMETER; + } + break; + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_RetrieveSwftFileOverride( + _In_ PVOID Context, + _In_ USHORT VendorID, + _In_ ULONG FileID, + _In_ USHORT SwftFileVersion, + _In_ ULONG SwftFileLength, + _Out_ PUSHORT NewFileVersion, + _Out_ PULONG NewFileLength, + _In_ ULONG NewFileBufferLength, + _Out_writes_bytes_opt_(NewFileBufferLength) + PVOID NewFileBuffer +) +{ + PAGED_CODE(); + const ULONG replaceFiles[][2] = { + // Using the Microsoft Vendor ID for testing and demonstration purposes - XU developer + // must use a different appropriate vendor ID + { 0x02cb, 0x00000001} + }; + const USHORT newFileVersion = 0x1010; + + BYTE newFileData[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; + + WDFDEVICE device = (WDFDEVICE)Context; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Handling SWFT File Override for VendorID %#x FileID %#x Swft Version %#x Length %d", + device, + VendorID, + FileID, + SwftFileVersion, + SwftFileLength); + + if (NewFileBufferLength > 0 && + (!NewFileVersion || !NewFileLength || !NewFileBuffer)) + { + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + else if (NewFileBufferLength == 0 && !NewFileLength) + { + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // An XU developer may choose to override a SWFT file only if the version matches certain criteria + // or they may choose to override based on other criteria or always. + for (ULONG file = 0; file < ARRAYSIZE(replaceFiles); ++file) + { + if (replaceFiles[file][0] == VendorID && replaceFiles[file][1] == FileID && SwftFileVersion < newFileVersion) + { + if (NewFileBufferLength >= sizeof(newFileData)) + { + DrvLogInfo(g_SDCAVXuLog, FLAG_INFO, + L"Device %p Overriding SWFT file for VendorID %#x FileID %#x, new Version %#x Length %d", + device, + VendorID, + FileID, + newFileVersion, + sizeof(newFileData)); + + RtlCopyMemory(NewFileBuffer, newFileData, sizeof(newFileData)); + *NewFileVersion = newFileVersion; + *NewFileLength = sizeof(newFileData); + return STATUS_SUCCESS; + } + else + { + *NewFileLength = sizeof(newFileData); + RETURN_NTSTATUS(STATUS_BUFFER_OVERFLOW); + } + } + } + + return STATUS_NOT_FOUND; +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +NTSTATUS +EvtSDCAVXuProcessQueryInterfaceRequest( + _In_ WDFDEVICE Device, + _In_ LPGUID InterfaceType, + _Inout_ PINTERFACE ExposedInterface, + _Inout_opt_ PVOID ExposedInterfaceSpecificData +) +{ + PAGED_CODE(); + + DrvLogEnter(g_SDCAVXuLog); + + NTSTATUS status = STATUS_SUCCESS; + + if (IsEqualGUID(*InterfaceType, SDCAXU_INTERFACE) && + ExposedInterface->Size >= sizeof(SDCAXU_INTERFACE_V0102)&& + ExposedInterface->Version == SDCAXU_INTERFACE_VERSION_0102) + { + PSDCAXU_INTERFACE_V0102 pSdcaXuInterface = PSDCAXU_INTERFACE_V0102(ExposedInterface); + + pSdcaXuInterface->InterfaceHeader.Context = Device; + pSdcaXuInterface->InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; + pSdcaXuInterface->InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; + + pSdcaXuInterface->EvtSetHwConfig = SdcaXu_SetHwConfig; + pSdcaXuInterface->EvtSetEndpointConfig = SdcaXu_SetEndpointConfig; + pSdcaXuInterface->EvtRemoveEndpointConfig = SdcaXu_RemoveEndpointConfig; + pSdcaXuInterface->EvtInterruptHandler = SdcaXu_InterruptHandler; + pSdcaXuInterface->EvtChangeNotification = SdcaXu_ChangeNotification; + pSdcaXuInterface->EvtRetrieveSwftFileOverride = SdcaXu_RetrieveSwftFileOverride; + + // + // Check if SDCA has provided its own functions for 2-way communication + // + if (pSdcaXuInterface->EvtSetXUEntities && + pSdcaXuInterface->EvtRegisterForInterrupts && + pSdcaXuInterface->EvtSetJackOverride && + pSdcaXuInterface->EvtSetJackSelectedMode && + pSdcaXuInterface->EvtPDEPowerReferenceAcquire && + pSdcaXuInterface->EvtPDEPowerReferenceRelease && + pSdcaXuInterface->EvtReadDeferredAudioControls && + pSdcaXuInterface->EvtWriteDeferredAudioControls) + { + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(Device); + + RtlZeroMemory(&devCtx->SDCADeviceData.SDCAInterface, sizeof(SDCAXU_INTERFACE_V0102)); + devCtx->SDCADeviceData.SDCAInterface.EvtSetXUEntities = pSdcaXuInterface->EvtSetXUEntities; + devCtx->SDCADeviceData.SDCAInterface.EvtRegisterForInterrupts = pSdcaXuInterface->EvtRegisterForInterrupts; + devCtx->SDCADeviceData.SDCAInterface.EvtSetJackOverride = pSdcaXuInterface->EvtSetJackOverride; + devCtx->SDCADeviceData.SDCAInterface.EvtSetJackSelectedMode = pSdcaXuInterface->EvtSetJackSelectedMode; + devCtx->SDCADeviceData.SDCAInterface.EvtPDEPowerReferenceAcquire = pSdcaXuInterface->EvtPDEPowerReferenceAcquire; + devCtx->SDCADeviceData.SDCAInterface.EvtPDEPowerReferenceRelease = pSdcaXuInterface->EvtPDEPowerReferenceRelease; + devCtx->SDCADeviceData.SDCAInterface.EvtReadDeferredAudioControls = pSdcaXuInterface->EvtReadDeferredAudioControls; + devCtx->SDCADeviceData.SDCAInterface.EvtWriteDeferredAudioControls = pSdcaXuInterface->EvtWriteDeferredAudioControls; + + devCtx->SDCADeviceData.SDCAContext = ExposedInterfaceSpecificData; + devCtx->SDCADeviceData.bSDCAInterface = WdfTrue; + } + } + else if (IsEqualGUID(*InterfaceType, SDCAXU_INTERFACE) && + ExposedInterface->Size >= sizeof(SDCAXU_INTERFACE_V0101)&& + ExposedInterface->Version == SDCAXU_INTERFACE_VERSION_0101) + { + PSDCAXU_INTERFACE_V0101 pSdcaXuInterface = PSDCAXU_INTERFACE_V0101(ExposedInterface); + + pSdcaXuInterface->InterfaceHeader.Context = Device; + pSdcaXuInterface->InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; + pSdcaXuInterface->InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; + + pSdcaXuInterface->EvtSetHwConfig = SdcaXu_SetHwConfig; + pSdcaXuInterface->EvtSetEndpointConfig = SdcaXu_SetEndpointConfig; + pSdcaXuInterface->EvtRemoveEndpointConfig = SdcaXu_RemoveEndpointConfig; + pSdcaXuInterface->EvtInterruptHandler = SdcaXu_InterruptHandler; + pSdcaXuInterface->EvtChangeNotification = SdcaXu_ChangeNotification; + + // + // Check if SDCA has provided its own functions for 2-way communication + // + if (pSdcaXuInterface->EvtSetXUEntities && + pSdcaXuInterface->EvtRegisterForInterrupts && + pSdcaXuInterface->EvtSetJackOverride && + pSdcaXuInterface->EvtSetJackSelectedMode && + pSdcaXuInterface->EvtPDEPowerReferenceAcquire && + pSdcaXuInterface->EvtPDEPowerReferenceRelease && + pSdcaXuInterface->EvtReadDeferredAudioControls && + pSdcaXuInterface->EvtWriteDeferredAudioControls) + { + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(Device); + + RtlZeroMemory(&devCtx->SDCADeviceData.SDCAInterface, sizeof(SDCAXU_INTERFACE_V0101)); + devCtx->SDCADeviceData.SDCAInterface.EvtSetXUEntities = pSdcaXuInterface->EvtSetXUEntities; + devCtx->SDCADeviceData.SDCAInterface.EvtRegisterForInterrupts = pSdcaXuInterface->EvtRegisterForInterrupts; + devCtx->SDCADeviceData.SDCAInterface.EvtSetJackOverride = pSdcaXuInterface->EvtSetJackOverride; + devCtx->SDCADeviceData.SDCAInterface.EvtSetJackSelectedMode = pSdcaXuInterface->EvtSetJackSelectedMode; + devCtx->SDCADeviceData.SDCAInterface.EvtPDEPowerReferenceAcquire = pSdcaXuInterface->EvtPDEPowerReferenceAcquire; + devCtx->SDCADeviceData.SDCAInterface.EvtPDEPowerReferenceRelease = pSdcaXuInterface->EvtPDEPowerReferenceRelease; + devCtx->SDCADeviceData.SDCAInterface.EvtReadDeferredAudioControls = pSdcaXuInterface->EvtReadDeferredAudioControls; + devCtx->SDCADeviceData.SDCAInterface.EvtWriteDeferredAudioControls = pSdcaXuInterface->EvtWriteDeferredAudioControls; + + devCtx->SDCADeviceData.SDCAContext = ExposedInterfaceSpecificData; + devCtx->SDCADeviceData.bSDCAInterface = WdfTrue; + } + } + else + { + status = STATUS_NOT_SUPPORTED; + } + + RETURN_NTSTATUS_IF_FAILED(status); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SDCAVXuAddDDI( + _In_ WDFDEVICE device +) +{ + PAGED_CODE(); + NTSTATUS status = STATUS_SUCCESS; + WDF_QUERY_INTERFACE_CONFIG qiConfig; + + // + // Initialize the qiConfig structure + // + WDF_QUERY_INTERFACE_CONFIG_INIT( + &qiConfig, + NULL, + &SDCAXU_INTERFACE, + EvtSDCAVXuProcessQueryInterfaceRequest + ); + + qiConfig.ImportInterface = WdfTrue; + + // + // Create the interface + // + RETURN_NTSTATUS_IF_FAILED(WdfDeviceAddQueryInterface(device, &qiConfig)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtBusDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit +) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. All the software resources + should be allocated in this callback. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + NTSTATUS status = STATUS_SUCCESS; + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = SdcaXu_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = SdcaXu_EvtDeviceReleaseHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + // + // Specify the type of context needed. + // Use default locking, i.e., none. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = SdcaXu_EvtDeviceContextCleanup; + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG devInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg)); + + WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); + + WdfFdoInitSetFilter(DeviceInit); + + // + // Create the device. + // + WDFDEVICE device = NULL; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device)); + + // + // Init SdcaXu's device context. + // + PSDCAXU_DEVICE_CONTEXT devCtx; + devCtx = GetSdcaXuDeviceContext(device); + ASSERT(devCtx != NULL); + devCtx->Render = NULL; + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg)); + + // + // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so + // that you don't get the popup in usermode (on Win2K) when you surprise + // remove the device. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.SurpriseRemovalOK = WdfTrue; + WdfDeviceSetPnpCapabilities(device, &pnpCaps); + + // + // Add QI based Direct Device Interface + // + RETURN_NTSTATUS_IF_FAILED(SDCAVXuAddDDI(device)); + + // + // Create Raw PDO for ACX circuits + // + RETURN_NTSTATUS_IF_FAILED(SDCAVXu_CreateCircuitDevice(device)); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status; + PSDCAXU_DEVICE_CONTEXT devCtx; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + devCtx = GetSdcaXuDeviceContext(Device); + ASSERT(devCtx != NULL); + + + status = STATUS_SUCCESS; + + return status; +} + +#pragma code_seg() +VOID +SdcaXu_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + PSDCAXU_DEVICE_CONTEXT devCtx; + + devCtx = GetSdcaXuDeviceContext(WdfDevice); + ASSERT(devCtx != NULL); + + if (devCtx) + { + for (ULONG i = 0; i < ARRAYSIZE(devCtx->EndpointDevices); ++i) + { + if (devCtx->EndpointDevices[i].CircuitUri.Buffer) + { + // Since the Buffer item is part of the actual context memory block, it's guaranteed to be 0-valued until we use it +#pragma prefast(suppress: 6001 , "C6001 Using uninitialized memor: Using uninitialized memory '*devCtx.EndpointDevices.CircuitUri.Buffer" ) + ExFreePool(devCtx->EndpointDevices[i].CircuitUri.Buffer); + RtlZeroMemory(&devCtx->EndpointDevices[i], sizeof(devCtx->EndpointDevices[i])); + } + } + } +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_ReplicateFormats( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +) +{ + PAGED_CODE(); + + // Using the opposite Pin Id to find the upstream pin only works here because + // we only register for EvtAcxPinConnected on the downstream pin and the XU circuit + // has only two pins (upstream and downstream). If the XU driver exposes more than + // two pins, the following logic would need to be updated to find correct upstream pin. + + ACXPIN upstreamPin; + if (AcxPinGetId(Pin) == 0) + { + upstreamPin = AcxCircuitGetPinById(AcxPinGetCircuit(Pin), 1); + } + else + { + upstreamPin = AcxCircuitGetPinById(AcxPinGetCircuit(Pin), 0); + } + + if (!upstreamPin) + { + RETURN_NTSTATUS(STATUS_UNSUCCESSFUL); + } + + ACXTARGETPIN targetPin = AcxTargetCircuitGetTargetPin(TargetCircuit, TargetPinId); + if (!targetPin) + { + RETURN_NTSTATUS(STATUS_UNSUCCESSFUL); + } + + // Don't delete the target pin - it will be cleaned up when the target circuit is cleaned up by ACX + + GUID targetModes[] = + { + AUDIO_SIGNALPROCESSINGMODE_RAW, + AUDIO_SIGNALPROCESSINGMODE_DEFAULT, + AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, + AUDIO_SIGNALPROCESSINGMODE_SPEECH + }; + + ULONG totalFormats = 0; + for (ULONG modeIdx = 0; modeIdx < ARRAYSIZE(targetModes); ++modeIdx) + { + ACXDATAFORMATLIST targetFormatList; + ACXDATAFORMATLIST localFormatList = nullptr; + NTSTATUS status = AcxTargetPinRetrieveModeDataFormatList(targetPin, targetModes+modeIdx, &targetFormatList); + if (!NT_SUCCESS(status)) + { + // If the downstream pin doesn't support any formats for this mode, make sure we clear out our host pin + // formats for this mode as well. + if (modeIdx == 0) + { + localFormatList = AcxPinGetRawDataFormatList(upstreamPin); + } + else + { + // Ignore the status + AcxPinRetrieveModeDataFormatList(upstreamPin, targetModes + modeIdx, &localFormatList); + } + if (localFormatList) + { + RETURN_NTSTATUS_IF_FAILED(SdcaVad_ClearDataFormatList(localFormatList)); + } + continue; + } + + RETURN_NTSTATUS_IF_FAILED(SdcaVad_RetrieveOrCreateDataFormatList(upstreamPin, targetModes + modeIdx, &localFormatList)); + + RETURN_NTSTATUS_IF_FAILED(SdcaVad_ClearDataFormatList(localFormatList)); + + ULONG formatCount = 0; + RETURN_NTSTATUS_IF_FAILED(SdcaVad_CopyFormats(targetFormatList, localFormatList, &formatCount)); + + totalFormats += formatCount; + } + + if (totalFormats == 0) + { + RETURN_NTSTATUS(STATUS_NO_MATCH); + } + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +VOID +SdcaXu_EvtPinConnected( + _In_ ACXPIN Pin, + _In_ ACXTARGETCIRCUIT TargetCircuit, + _In_ ULONG TargetPinId +) +{ + NTSTATUS status; + + PAGED_CODE(); + + // Call the worker so we can trace the return of failures + status = SdcaXu_ReplicateFormats(Pin, TargetCircuit, TargetPinId); + + // If we found no formats, there's not much we can do about it. + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVXuLog, FLAG_INIT, L"Failed to replicate downstream formats to upstream pin, %!STATUS!", status); + } +} + +#pragma code_seg() +VOID +SdcaXu_EvtStreamDestroy( + _In_ WDFOBJECT Object +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + NTSTATUS status = STATUS_SUCCESS; + auto exit = scope_exit([&status]() { + if (!NT_SUCCESS(status)) + { + DrvLogError(g_SDCAVXuLog, FLAG_INIT, L"SdcaXu_EvtStreamDestroy - failed, %!STATUS!", status); + } + }); + + ctx = GetSdcaXuStreamContext((ACXSTREAM)Object); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + ctx->StreamEngine = NULL; + if (streamEngine) + { + delete streamEngine; + } +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamGetHwLatency( + _In_ ACXSTREAM Stream, + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->GetHWLatency(FifoSize, Delay); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamPrepareHardware( + _In_ ACXSTREAM Stream +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->PrepareHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamReleaseHardware( + _In_ ACXSTREAM Stream +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->ReleaseHardware(); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamRun( + _In_ ACXSTREAM Stream +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Run(); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamPause( + _In_ ACXSTREAM Stream +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->Pause(); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_EvtStreamAssignDrmContentId( + _In_ ACXSTREAM Stream, + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights +) +{ + PSDCAXU_STREAM_CONTEXT ctx; + CStreamEngine * streamEngine = NULL; + + PAGED_CODE(); + + ctx = GetSdcaXuStreamContext(Stream); + + streamEngine = (CStreamEngine*)ctx->StreamEngine; + + return streamEngine->AssignDrmContentId(DrmContentId, DrmRights); +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.cpp new file mode 100644 index 00000000..775094ee --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.cpp @@ -0,0 +1,178 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + Driver.cpp + +Abstract: + + Sample Soundwire Extension Unit Driver. + +Environment: + + Kernel mode only + +--*/ + +#include "private.h" +#include "trace.h" +#include "driver.h" + +#ifndef __INTELLISENSE__ +#include "driver.tmh" +#endif + +RECORDER_LOG g_SDCAVXuLog; + +// When creating private drops, use set C_DEFINES=-DDROP_STAMP=nnnn to add the drop timestamp to the initial trace +#ifndef DROP_STAMP +#define DROP_STAMP 0 +#endif + +PAGED_CODE_SEG +void SdcaXu_DriverUnload (_In_ WDFDRIVER Driver) +{ + PAGED_CODE(); + + if (!Driver) + { + ASSERT(FALSE); + return; + } + + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); + + return; +} + +INIT_CODE_SEG +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + + WPP_INIT_TRACING(DriverObject, RegistryPath); + + auto exit = scope_exit([&status, &DriverObject]() { + if (!NT_SUCCESS(status)) + { + if (g_RegistryPath.Buffer != NULL) + { + ExFreePool(g_RegistryPath.Buffer); + RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath)); + } + + WPP_CLEANUP(DriverObject); + } + }); + + RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath)); + + // + // Initiialize 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, + // you can override that by manually setting the EvtDriverUnload in the + // config structure. In general xxx_CONFIG_INIT macros are provided to + // initialize most commonly used members. + // + + WDF_DRIVER_CONFIG wdfCfg; + WDF_DRIVER_CONFIG_INIT(&wdfCfg, SdcaXu_EvtBusDeviceAdd); + wdfCfg.EvtDriverUnload = SdcaXu_DriverUnload; + + // + // Add a driver context. (for illustration purposes only). + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_DRIVER_CONTEXT); + + // + // Create a framework driver object to represent our driver. + // + WDFDRIVER driver; + RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, // Driver Attributes + &wdfCfg, // Driver Config Info + &driver // hDriver + )); + + RECORDER_CONFIGURE_PARAMS recorderConfig; + RECORDER_CONFIGURE_PARAMS_INIT(&recorderConfig); + recorderConfig.CreateDefaultLog = FALSE; + WppRecorderConfigure(&recorderConfig); + + RECORDER_LOG_CREATE_PARAMS recorderLogCreateParams; + RECORDER_LOG_CREATE_PARAMS_INIT(&recorderLogCreateParams, NULL); + recorderLogCreateParams.TotalBufferSize = WPP_TOTAL_BUFFER_SIZE; + recorderLogCreateParams.ErrorPartitionSize = WPP_ERROR_PARTITION_SIZE; + + RtlStringCbPrintfA(recorderLogCreateParams.LogIdentifier, + RECORDER_LOG_IDENTIFIER_MAX_CHARS, + "SDCAVXu"); + + RECORDER_LOG logHandle = NULL; + status = WppRecorderLogCreate(&recorderLogCreateParams, &logHandle); + if (!NT_SUCCESS(status)) + { + logHandle = NULL; + + // Non fatal failure + status = STATUS_SUCCESS; + } + + g_SDCAVXuLog = logHandle; + + DrvLogInfo(g_SDCAVXuLog, FLAG_INIT, "SdcaVXu Driver loaded, %lld", DROP_STAMP); + + // + // Post init. + // + ACX_DRIVER_CONFIG acxCfg; + ACX_DRIVER_CONFIG_INIT(&acxCfg); + + RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg)); + + return status; +} + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.h new file mode 100644 index 00000000..0666a3d7 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/driver.h @@ -0,0 +1,35 @@ +/*++ + +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: + + driver.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +EVT_WDF_DRIVER_UNLOAD SdcaXu_DriverUnload; + +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath +); + +#pragma code_seg() diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/private.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/private.h new file mode 100644 index 00000000..e39c857d --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/private.h @@ -0,0 +1,422 @@ +/*++ + +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: + + private.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#ifndef _PRIVATE_H_ +#define _PRIVATE_H_ + +#include "cpp_utils.h" + +#include "stdunk.h" +#include <mmsystem.h> +#include <ks.h> + +#include "NewDelete.h" + +/* make prototypes usable from C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +#pragma warning(disable:4200) // +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int + +#include <initguid.h> +#include <ntddk.h> +#include <ntstrsafe.h> +#include <ntintsafe.h> + +#pragma warning(default:4200) +#pragma warning(default:4201) +#pragma warning(default:4214) + +#include <wdf.h> +#include <acx.h> + +#include "SoundWireController.h" +#include "SdcaXu.h" + +#include "Trace.h" + +#define PAGED_CODE_SEG __declspec(code_seg("PAGE")) +#define INIT_CODE_SEG __declspec(code_seg("INIT")) + +extern RECORDER_LOG g_SDCAVXuLog; + +// Simple ACX driver +#define DRIVER_TAG (ULONG) 'Ecds' + +// Number of msec for idle timeout. +#define IDLE_POWER_TIMEOUT 5000 + +// Number of millisecs per sec. +#define MS_PER_SEC 1000 + +// Number of hundred nanosecs per sec. +#define HNS_PER_SEC 10000000 + +// Compatible ID for render/capture +#define SDCAVAD_COMPATIBLE_ID L"{2172A9B3-0690-4BB6-88FF-B778E999E04A}" + +// Container ID for render/capture +#define SDCAVAD_CONTAINER_ID L"{00000000-0000-0000-ffff-ffffffffffff}" + +// Bridge Pin Number for Circuit +const ULONG _BRIDGE_PIN_ID = 1; + +#undef MIN +#undef MAX +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifndef BOOL +typedef int BOOL; +#endif + +#ifndef SIZEOF_ARRAY +#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) +#endif // !defined(SIZEOF_ARRAY) + +#define SDCA_INTERRUPT_DEFINE_MASK(Mask, ...)\ + {\ + unsigned char parameters[] = {__VA_ARGS__};\ + for(unsigned char iParameter = 0; iParameter < SIZEOF_ARRAY(parameters); iParameter ++) \ + {\ + Mask = Mask | (0x1<<(unsigned long)parameters[iParameter]); \ + }\ + }\ + +#ifdef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS +#define STATIC_KSPROPERTYSETID_AcxCircuit\ + 0x4d12807eL, 0x55db, 0x48b8, 0xa4, 0x66, 0xf1, 0x5a, 0x51, 0x0f, 0x58, 0x17 +DEFINE_GUIDSTRUCT("4d12807e-55db-48b8-a466-f15a510f5817", KSPROPERTYSETID_AcxCircuit); +#define KSPROPERTYSETID_AcxCircuit DEFINE_GUIDNAMED(KSPROPERTYSETID_AcxCircuit) + +typedef enum { + KSPROPERTY_ACXCIRCUIT_INFORMATION = 1, // get + KSPROPERTY_ACXCIRCUIT_SETNOTIFICATIONDEVICE, + KSPROPERTY_ACXCIRCUIT_SETNOTIFICATIONID, + KSPROPERTY_ACXCIRCUIT_SETINSTANCEID, +} KSPROPERTY_ACXCIRCUIT; +#endif + +// NULL GUID +static const GUID NULL_GUID = +{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; + +// +// Example Acpi blob for Hardware configuration +// +typedef struct _SdcaXuAcpiBlob +{ + // Number of endpoints + ULONG NumEndpoints; + +}SdcaXuAcpiBlob, *PSdcaXuAcpiBlob; + +// Test Structure so the Extension Unit Driver can do the right things. +typedef struct _EXTENSION_UNIT_HW_DATA +{ + UINT8 AvailableXUEntities[8]; + UINT8 AvailableGroupEntities[8]; +} EXTENSION_UNIT_HW_DATA, * PEXTENSION_UNIT_HW_DATA; + +// +// Define XU driver context. +// +typedef struct _SDCAXU_DRIVER_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_DRIVER_CONTEXT, *PSDCAXU_DRIVER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_DRIVER_CONTEXT, GetSdcaXuDriverContext) + +typedef struct _SDCA_DEVICE_DATA +{ + BOOLEAN bSDCAInterface; + PVOID SDCAContext; + SDCAXU_INTERFACE_V0101 SDCAInterface; + + ULONG NumEndpoints; + EXTENSION_UNIT_HW_DATA HwData; +}SDCA_DEVICE_DATA, * PSDCA_DEVICE_DATA; + +#define MAX_ENDPOINT_COUNT 6 +typedef struct _ENDPOINT_DEVICE_PAIR +{ + GUID CircuitId; + UNICODE_STRING CircuitUri; + WDFDEVICE CircuitDevice; +}ENDPOINT_DEVICE_PAIR, *PENDPOINT_DEVICE_PAIR; +// +// Define XU device context. +// +typedef struct _SDCAXU_DEVICE_CONTEXT { + ACXCIRCUIT Render; + ACXCIRCUIT Capture; + SDCA_DEVICE_DATA SDCADeviceData; + WDFDEVICE CircuitDevice; + + ENDPOINT_DEVICE_PAIR EndpointDevices[MAX_ENDPOINT_COUNT]; +} SDCAXU_DEVICE_CONTEXT, *PSDCAXU_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_DEVICE_CONTEXT, GetSdcaXuDeviceContext) + +// +// Define Circuit Device context. +// +typedef struct _SDCAXU_CIRCUIT_DEVICE_CONTEXT { + BOOLEAN FirstTimePrepareHardware; +} SDCAXU_CIRCUIT_DEVICE_CONTEXT, *PSDCAXU_CIRCUIT_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_CIRCUIT_DEVICE_CONTEXT, GetCircuitDeviceContext) + +// +// Define circuit context for module-hosting circuit. +// +typedef struct _SdcaXuMODULECIRCUIT_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_MODULECIRCUIT_CONTEXT, *PSDCAXU_MODULECIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_MODULECIRCUIT_CONTEXT, GetModuleCircuitContext) + +// +// Define RENDER device context. +// +typedef struct _SDCAXU_RENDER_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} SDCAXU_RENDER_DEVICE_CONTEXT, *PSDCAXU_RENDER_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_RENDER_DEVICE_CONTEXT, GetRenderDeviceContext) + +// +// Define RENDER circuit context. +// +typedef struct _SDCAXU_RENDER_CIRCUIT_CONTEXT { + PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig; + ULONG CommitGroupHandle; +#ifdef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + WDFDEVICE EndpointDevice; + WDFIOTARGET WdfIoNotificationTarget; + GUID PnpNotificationId; + DWORD InstanceId; +#endif +} SDCAXU_RENDER_CIRCUIT_CONTEXT, *PSDCAXU_RENDER_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_RENDER_CIRCUIT_CONTEXT, GetRenderCircuitContext) + +// +// Define CAPTURE device context. +// +typedef struct _SDCAXU_CAPTURE_DEVICE_CONTEXT { + ACXCIRCUIT Circuit; + BOOLEAN FirstTimePrepareHardware; +} SDCAXU_CAPTURE_DEVICE_CONTEXT, *PSDCAXU_CAPTURE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext) + +// +// Define CAPTURE circuit context. +// +typedef struct _SDCAXU_CAPTURE_CIRCUIT_CONTEXT { + PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig; +} SDCAXU_CAPTURE_CIRCUIT_CONTEXT, *PSDCAXU_CAPTURE_CIRCUIT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_CAPTURE_CIRCUIT_CONTEXT, GetCaptureCircuitContext) + +// +// Define XU render/capture stream context. +// +typedef struct _SDCAXU_STREAM_CONTEXT { + PVOID StreamEngine; +} SDCAXU_STREAM_CONTEXT, *PSDCAXU_STREAM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_STREAM_CONTEXT, GetSdcaXuStreamContext) + +// +// Define XU circuit/stream element context. +// +typedef struct _SDCAXU_ELEMENT_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_ELEMENT_CONTEXT, *PSDCAXU_ELEMENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_ELEMENT_CONTEXT, GetSdcaXuElementContext) + +// +// Define XU format context. +// +typedef struct _SDCAXU_FORMAT_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_FORMAT_CONTEXT, *PSDCAXU_FORMAT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_FORMAT_CONTEXT, GetSdcaXuFormatContext) + +typedef struct _SDCAXU_PIN_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_PIN_CONTEXT, *PSDCAXU_PIN_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_PIN_CONTEXT, GetSdcaXuPinContext) + +typedef struct _SDCAXU_PNPEVENT_CONTEXT { + BOOLEAN Dummy; +} SDCAXU_PNPEVENT_CONTEXT, *PSDCAXU_PNPEVENT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SDCAXU_PNPEVENT_CONTEXT, GetSdcaXuPnpEventContext) + + +// +// Driver prototypes. +// +DRIVER_INITIALIZE DriverEntry; +DRIVER_UNLOAD SdcaXu_DriverUnload; +EVT_WDF_DRIVER_DEVICE_ADD SdcaXu_EvtBusDeviceAdd; + +// Device callbacks. + +EVT_WDF_DEVICE_PREPARE_HARDWARE SdcaXu_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE SdcaXu_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXu_EvtDeviceContextCleanup; + +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SdcaXu_EvtIoDeviceControl; + +EVT_ACX_PIN_CONNECTED SdcaXu_EvtPinConnected; + +// Stream callbacks shared between Capture and Render + +EVT_WDF_OBJECT_CONTEXT_DESTROY SdcaXu_EvtStreamDestroy; +EVT_ACX_STREAM_GET_HW_LATENCY SdcaXu_EvtStreamGetHwLatency; +EVT_ACX_STREAM_PREPARE_HARDWARE SdcaXu_EvtStreamPrepareHardware; +EVT_ACX_STREAM_RELEASE_HARDWARE SdcaXu_EvtStreamReleaseHardware; +EVT_ACX_STREAM_RUN SdcaXu_EvtStreamRun; +EVT_ACX_STREAM_PAUSE SdcaXu_EvtStreamPause; +EVT_ACX_STREAM_ASSIGN_DRM_CONTENT_ID SdcaXu_EvtStreamAssignDrmContentId; + +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUITDEVICE SdcaXu_EvtAcxFactoryCircuitCreateCircuitDevice; +EVT_ACX_FACTORY_CIRCUIT_CREATE_CIRCUIT SdcaXu_EvtAcxFactoryCircuitCreateCircuit; + +/* make internal prototypes usable from C++ */ +#ifdef __cplusplus +} +#endif + +// +// Used to store the registry settings path for the driver +// +extern UNICODE_STRING g_RegistryPath; + +__drv_requiresIRQL(PASSIVE_LEVEL) +PAGED_CODE_SEG +NTSTATUS +CopyRegistrySettingsPath( + _In_ PUNICODE_STRING RegistryPath +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddRenders( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddCaptures( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetHwConfig +( + _In_ PVOID Context, + _In_ SDCAXU_HW_CONFIG_TYPE HwConfigType, + _In_opt_ PVOID HwConfigData, + _In_ ULONG HwConfigDataSize +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetEndpointConfig +( + _In_ PVOID Context, + _In_ SDCAXU_ENDPOINT_CONFIG_TYPE EndpointConfigType, + _In_opt_ PVOID EndpointConfigData, + _In_ ULONG EndpointConfigDataSize +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SDCAInterruptHandler +( + _In_ PVOID Context, + _In_ ULONG SDCAInterruptBit +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SCPInterruptHandler +( + _In_ PVOID Context, + _In_ ULONG SCPInterruptBit +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_DataPortInterruptHandler +( + _In_ PVOID Context, + _In_ ULONG DataPort, + _In_ ULONG DataPortInterruptBit +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_ChangeNotification +( + _In_ PVOID Context, + _In_ SDCAXU_NOTIFICATION_TYPE NotificationType, + _In_opt_ PVOID NotificationData, + _In_ ULONG NotificationDataSize +); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetXUEntities(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_RegisterForInterrupts(_In_ WDFDEVICE Device); + +PAGED_CODE_SEG +NTSTATUS SdcaXu_SetJackOverride(_In_ WDFDEVICE Device); + +EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST EvtSDCAVXuProcessQueryInterfaceRequest; + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_ConfigureTestInterface( + _In_ WDFDEVICE Device, + _In_ PCGUID Interface +); + +#endif // _PRIVATE_H_ diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.cpp new file mode 100644 index 00000000..10d2e705 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.cpp @@ -0,0 +1,2093 @@ +/*++ + + 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: + + Render.cpp + +Abstract: + + Plug and Play module. This file contains routines to handle pnp requests. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> + +#include "render.h" + +#include "streamengine.h" + +#include "AudioFormats.h" + +#include "audiomodule.h" + +#include "audioaggregation.h" + +#ifndef __INTELLISENSE__ +#include "render.tmh" +#endif + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_EvtAcxPinSetDataFormat ( + _In_ ACXPIN Pin, + _In_ ACXDATAFORMAT DataFormat + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(DataFormat); + + + return STATUS_NOT_SUPPORTED; +} + +#pragma code_seg() +VOID +SdcaXuR_EvtPinContextCleanup( + _In_ WDFOBJECT WdfPin + ) +/*++ + +Routine Description: + + In this callback, it cleans up pin context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + UNREFERENCED_PARAMETER(WdfPin); +} + +VOID SdcaXuR_EvtCircuitContextCleanup(_In_ WDFOBJECT Object) +{ + ACXCIRCUIT circuit = (ACXCIRCUIT)Object; + PSDCAXU_RENDER_CIRCUIT_CONTEXT cirCtx = GetRenderCircuitContext(circuit); + + if (cirCtx->CircuitConfig) + { + ExFreePoolWithTag(cirCtx->CircuitConfig, DRIVER_TAG); + cirCtx->CircuitConfig = NULL; + } + +#ifdef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + if (cirCtx->WdfIoNotificationTarget) + { + WdfObjectDelete(cirCtx->WdfIoNotificationTarget); + cirCtx->WdfIoNotificationTarget = nullptr; + } + + cirCtx->PnpNotificationId = GUID_NULL; + cirCtx->InstanceId = 0; + cirCtx->EndpointDevice = nullptr; +#endif + + return; +} + +PAGED_CODE_SEG +VOID +SdcaXuR_EvtCircuitRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + +// to handle module notifications directly, the following needs to be intercepted +// with the values cached, so that the XU has them available to compose the stream +// module notifications. +#ifdef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + if (Object != nullptr) + { + NTSTATUS status = STATUS_SUCCESS; + ACX_REQUEST_PARAMETERS params; + PSDCAXU_RENDER_CIRCUIT_CONTEXT cirCtx; + + cirCtx = GetRenderCircuitContext(Object); + + ACX_REQUEST_PARAMETERS_INIT(¶ms); + AcxRequestGetParameters(Request, ¶ms); + + if(params.Type == AcxRequestTypeProperty && + params.Parameters.Property.Set == KSPROPERTYSETID_AcxCircuit) + { + switch(params.Parameters.Property.Id) + { + case KSPROPERTY_ACXCIRCUIT_SETNOTIFICATIONDEVICE: + { + WDF_OBJECT_ATTRIBUTES ioTargetAttrib; + WDFIOTARGET ioTarget = nullptr; + WDF_IO_TARGET_OPEN_PARAMS openParams; + UNICODE_STRING symbolicLinkName = {0}; + + if (params.Parameters.Property.Verb != AcxPropertyVerbSet) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + if (params.Parameters.Property.ValueCb == 0) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + status = RtlStringCbLengthW( + (LPCWSTR) params.Parameters.Property.Value, + params.Parameters.Property.ValueCb, // maximum buffer size, including NULL termination + NULL // optional returned lenght, not used. + ); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + status = RtlUnicodeStringInitEx(&symbolicLinkName, (LPCWSTR) params.Parameters.Property.Value, 0); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + WDF_OBJECT_ATTRIBUTES_INIT(&ioTargetAttrib); + ioTargetAttrib.ParentObject = cirCtx->EndpointDevice; + status = WdfIoTargetCreate( + cirCtx->EndpointDevice, + &ioTargetAttrib, + &ioTarget + ); + if (!NT_SUCCESS(status)) + { + goto exit; + } + + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( + &openParams, + &symbolicLinkName, + STANDARD_RIGHTS_ALL + ); + status = WdfIoTargetOpen( + ioTarget, + &openParams + ); + if (!NT_SUCCESS(status)) + { + WdfObjectDelete(ioTarget); + goto exit; + } + + if (cirCtx->WdfIoNotificationTarget) + { + WdfObjectDelete(cirCtx->WdfIoNotificationTarget); + cirCtx->WdfIoNotificationTarget = nullptr; + } + + cirCtx->WdfIoNotificationTarget = ioTarget; + ioTarget = nullptr; + } + break; + case KSPROPERTY_ACXCIRCUIT_SETNOTIFICATIONID: + { + if (params.Parameters.Property.Verb != AcxPropertyVerbSet) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + if (params.Parameters.Property.ValueCb != sizeof(GUID)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + cirCtx->PnpNotificationId = *((LPGUID) params.Parameters.Property.Value); + } + break; + case KSPROPERTY_ACXCIRCUIT_SETINSTANCEID: + { + if (params.Parameters.Property.Verb != AcxPropertyVerbSet) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + if (params.Parameters.Property.ValueCb != sizeof(DWORD)) + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + cirCtx->InstanceId = *((PDWORD) params.Parameters.Property.Value); + } + break; + } + } + + if (!NT_SUCCESS(status)) + { + DrvLogWarning(g_SDCAVXuLog, FLAG_INIT, L"SdcaXuR_EvtCircuitRequestPreprocess - failure, %!STATUS!", status); + } + } +exit: +#endif + + // + // Just give the request back to ACX. + // + (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request); +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +VOID +SdcaXuR_EvtStreamRequestPreprocess( + _In_ ACXOBJECT Object, + _In_ ACXCONTEXT DriverContext, + _In_ WDFREQUEST Request + ) +/*++ + +Routine Description: + + This function is an example of a preprocess routine. + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DriverContext); + + ASSERT(Object != NULL); + ASSERT(DriverContext); + ASSERT(Request); + + + // + // Just give the request back to ACX. + // + (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_SetPowerPolicy( + _In_ WDFDEVICE Device +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + + PAGED_CODE(); + + // + // Init the idle policy structure. + // + //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0); + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + idleSettings.IdleTimeout = IDLE_POWER_TIMEOUT; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + + status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_EvtDevicePrepareHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceList, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver does whatever is necessary to make the + hardware ready to use. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(ResourceList); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + if (!devCtx->FirstTimePrepareHardware) + { + // + // This is a rebalance. Validate the circuit resources and + // if needed, delete and re-create the circuit. + // The sample driver doens't use resources, thus the existing + // circuits are kept. + // + return STATUS_SUCCESS; + } + + // + // Set child's power policy. + // + RETURN_NTSTATUS_IF_FAILED(SdcaXuR_SetPowerPolicy(Device)); + + // + // Add circuit to child's list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Circuit)); + + // + // Keep track this is not the first time this callback was called. + // + devCtx->FirstTimePrepareHardware = FALSE; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_EvtDeviceReleaseHardware( + _In_ WDFDEVICE Device, + _In_ WDFCMRESLIST ResourceListTranslated +) +/*++ + +Routine Description: + + In this callback, the driver releases the h/w resources allocated in the + prepare h/w callback. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(ResourceListTranslated); + + PAGED_CODE(); + + PSDCAXU_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + + return status; +} + +PAGED_CODE_SEG +VOID +SdcaXuR_EvtDeviceContextCleanup( + _In_ WDFOBJECT WdfDevice +) +/*++ + +Routine Description: + + In this callback, it cleans up render device context. + +Arguments: + + WdfDevice - WDF device object + +Return Value: + + NULL + +--*/ +{ + PAGED_CODE(); + UNREFERENCED_PARAMETER(WdfDevice); +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_EvtDeviceSelfManagedIoInit( + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + + In this callback, the driver does one-time init of self-managed I/O data. + +Arguments: + + Device - handle to a device + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + PSDCAXU_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +#pragma code_seg("PAGE") +NTSTATUS +SdcaXu_EvtProcessCommand0( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PSDCAXU_AUDIOMODULE0_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetSdcaXuAudioModule0Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule0_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule0_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule0_ParameterInfo[AudioModuleParameter2]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = NULL; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + +#ifndef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); +#else + if (audioModuleCtx->Circuit == nullptr) + { + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + else + { + PSDCAXU_RENDER_CIRCUIT_CONTEXT cirCtx; + + cirCtx = GetRenderCircuitContext(audioModuleCtx->Circuit); + + // AcxPnpEventGenerateEvent will target the wrong PnpNotificationId, InstanceId, and IoTarget due to a lack + // of acx framework support. Compose the PNP notification manually and send it. + USHORT sizeRequired = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer) + sizeof(KSAUDIOMODULE_NOTIFICATION) + sizeof(customNotification); + PTARGET_DEVICE_CUSTOM_NOTIFICATION pCustomNotify = (PTARGET_DEVICE_CUSTOM_NOTIFICATION) new(POOL_FLAG_NON_PAGED, DRIVER_TAG) BYTE[sizeRequired]; + if (pCustomNotify != nullptr) + { + RtlZeroMemory(pCustomNotify, sizeRequired); + + pCustomNotify->NameBufferOffset = -1; + pCustomNotify->Version = 1; + pCustomNotify->Size = sizeRequired; + pCustomNotify->Event = KSNOTIFICATIONID_AudioModule; + + PKSAUDIOMODULE_NOTIFICATION pModuleNotify = (PKSAUDIOMODULE_NOTIFICATION) &(pCustomNotify->CustomDataBuffer[0]); + pModuleNotify->ProviderId.DeviceId = cirCtx->PnpNotificationId; + pModuleNotify->ProviderId.ClassId = AudioModule0Id; + pModuleNotify->ProviderId.InstanceId = (AUDIOMODULE_INSTANCE_ID(0,0) | cirCtx->InstanceId); + RtlCopyMemory(pModuleNotify + 1, &customNotification, sizeof(customNotification)); + + if (cirCtx->WdfIoNotificationTarget) + { + PDEVICE_OBJECT devObj = WdfIoTargetWdmGetTargetPhysicalDevice(cirCtx->WdfIoNotificationTarget); + + // if the notification target is invalidated, retrieving the physical device will fail and we can't send the event. + if (devObj) + { + IoReportTargetDeviceChangeAsynchronous(devObj, + pCustomNotify, + NULL, + NULL); + } + } + + delete[] pCustomNotify; + } + } +#endif + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +#pragma code_seg("PAGE") +NTSTATUS +SdcaXu_EvtProcessCommand1( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PSDCAXU_AUDIOMODULE1_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetSdcaXuAudioModule1Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule1_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter2]; + break; + case AudioModuleParameter3: + currentValue = &audioModuleCtx->Parameter3; + parameterInfo = &AudioModule1_ParameterInfo[AudioModuleParameter3]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = nullptr; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + +#ifndef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); +#else + if (audioModuleCtx->Circuit == nullptr) + { + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + else + { + PSDCAXU_RENDER_CIRCUIT_CONTEXT cirCtx; + + cirCtx = GetRenderCircuitContext(audioModuleCtx->Circuit); + + // AcxPnpEventGenerateEvent will target the wrong PnpNotificationId, InstanceId, and IoTarget due to a lack + // of acx framework support. Compose the PNP notification manually and send it. + USHORT sizeRequired = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer) + sizeof(KSAUDIOMODULE_NOTIFICATION) + sizeof(customNotification); + PTARGET_DEVICE_CUSTOM_NOTIFICATION pCustomNotify = (PTARGET_DEVICE_CUSTOM_NOTIFICATION) new(POOL_FLAG_NON_PAGED, DRIVER_TAG) BYTE[sizeRequired]; + if (pCustomNotify != nullptr) + { + RtlZeroMemory(pCustomNotify, sizeRequired); + + pCustomNotify->NameBufferOffset = -1; + pCustomNotify->Version = 1; + pCustomNotify->Size = sizeRequired; + pCustomNotify->Event = KSNOTIFICATIONID_AudioModule; + + PKSAUDIOMODULE_NOTIFICATION pModuleNotify = (PKSAUDIOMODULE_NOTIFICATION) &(pCustomNotify->CustomDataBuffer[0]); + pModuleNotify->ProviderId.DeviceId = cirCtx->PnpNotificationId; + pModuleNotify->ProviderId.ClassId = AudioModule1Id; + pModuleNotify->ProviderId.InstanceId = (AUDIOMODULE_INSTANCE_ID(0,0) | cirCtx->InstanceId); + RtlCopyMemory(pModuleNotify + 1, &customNotification, sizeof(customNotification)); + + if (cirCtx->WdfIoNotificationTarget) + { + PDEVICE_OBJECT devObj = WdfIoTargetWdmGetTargetPhysicalDevice(cirCtx->WdfIoNotificationTarget); + + // if the notification target is invalidated, retrieving the physical device will fail and we can't send the event. + if (devObj) + { + IoReportTargetDeviceChangeAsynchronous(devObj, + pCustomNotify, + NULL, + NULL); + } + } + + delete[] pCustomNotify; + } + } +#endif + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +#pragma code_seg("PAGE") +NTSTATUS +SdcaXu_EvtProcessCommand2( + _In_ ACXAUDIOMODULE AudioModule, + _In_ PVOID InBuffer, + _In_ ULONG InBufferCb, + _In_ PVOID OutBuffer, + _Inout_ PULONG OutBufferCb + ) +{ + BOOL fNewValue = FALSE; + PVOID currentValue = nullptr; + PVOID inBuffer = nullptr; + ULONG inBufferCb = 0; + PSDCAXU_AUDIOMODULE2_CONTEXT audioModuleCtx; + AUDIOMODULE_PARAMETER_INFO * parameterInfo = nullptr; + AUDIOMODULE_CUSTOM_COMMAND * command = nullptr; + + PAGED_CODE(); + + audioModuleCtx = GetSdcaXuAudioModule2Context(AudioModule); + RETURN_NTSTATUS_IF_TRUE(nullptr == audioModuleCtx, STATUS_INTERNAL_ERROR); + + // + // Basic parameter validation (module specific). + // + RETURN_NTSTATUS_IF_TRUE(InBuffer == nullptr || InBufferCb == 0, STATUS_INVALID_PARAMETER); + RETURN_NTSTATUS_IF_TRUE(InBufferCb < sizeof(AUDIOMODULE_CUSTOM_COMMAND), STATUS_INVALID_PARAMETER); + + command = (AUDIOMODULE_CUSTOM_COMMAND*)InBuffer; + + RETURN_NTSTATUS_IF_TRUE(command->ParameterId >= SIZEOF_ARRAY(AudioModule2_ParameterInfo), STATUS_INVALID_PARAMETER); + + // + // Validate the parameter referenced in the command. + // + switch (command->ParameterId) + { + case AudioModuleParameter1: + currentValue = &audioModuleCtx->Parameter1; + parameterInfo = &AudioModule2_ParameterInfo[AudioModuleParameter1]; + break; + case AudioModuleParameter2: + currentValue = &audioModuleCtx->Parameter2; + parameterInfo = &AudioModule2_ParameterInfo[AudioModuleParameter2]; + break; + default: + RETURN_NTSTATUS(STATUS_INVALID_PARAMETER); + } + + // + // Update input buffer ptr/size. + // + inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE_CUSTOM_COMMAND)); + inBufferCb = InBufferCb - sizeof(AUDIOMODULE_CUSTOM_COMMAND); + + if (inBufferCb == 0) + { + inBuffer = nullptr; + } + + RETURN_NTSTATUS_IF_FAILED(AudioModule_GenericHandler( + command->Verb, + command->ParameterId, + parameterInfo, + currentValue, + inBuffer, + inBufferCb, + OutBuffer, + OutBufferCb, + &fNewValue)); + + if (fNewValue && + (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION)) + { + AUDIOMODULE_CUSTOM_NOTIFICATION customNotification = {0}; + + customNotification.Type = AudioModuleParameterChanged; + customNotification.ParameterChanged.ParameterId = command->ParameterId; + +#ifndef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); +#else + if (audioModuleCtx->Circuit == nullptr) + { + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventGenerateEvent(audioModuleCtx->Event, &customNotification, (USHORT)sizeof(customNotification))); + } + else + { + PSDCAXU_RENDER_CIRCUIT_CONTEXT cirCtx; + + cirCtx = GetRenderCircuitContext(audioModuleCtx->Circuit); + + // AcxPnpEventGenerateEvent will target the wrong PnpNotificationId, InstanceId, and IoTarget due to a lack + // of acx framework support. Compose the PNP notification manually and send it. + USHORT sizeRequired = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer) + sizeof(KSAUDIOMODULE_NOTIFICATION) + sizeof(customNotification); + PTARGET_DEVICE_CUSTOM_NOTIFICATION pCustomNotify = (PTARGET_DEVICE_CUSTOM_NOTIFICATION) new(POOL_FLAG_NON_PAGED, DRIVER_TAG) BYTE[sizeRequired]; + if (pCustomNotify != nullptr) + { + RtlZeroMemory(pCustomNotify, sizeRequired); + + pCustomNotify->NameBufferOffset = -1; + pCustomNotify->Version = 1; + pCustomNotify->Size = sizeRequired; + pCustomNotify->Event = KSNOTIFICATIONID_AudioModule; + + PKSAUDIOMODULE_NOTIFICATION pModuleNotify = (PKSAUDIOMODULE_NOTIFICATION) &(pCustomNotify->CustomDataBuffer[0]); + pModuleNotify->ProviderId.DeviceId = cirCtx->PnpNotificationId; + pModuleNotify->ProviderId.ClassId = AudioModule2Id; + pModuleNotify->ProviderId.InstanceId = (AUDIOMODULE_INSTANCE_ID(1,0) | cirCtx->InstanceId); + RtlCopyMemory(pModuleNotify + 1, &customNotification, sizeof(customNotification)); + + if (cirCtx->WdfIoNotificationTarget) + { + PDEVICE_OBJECT devObj = WdfIoTargetWdmGetTargetPhysicalDevice(cirCtx->WdfIoNotificationTarget); + + // if the notification target is invalidated, retrieving the physical device will fail and we can't send the event. + if (devObj) + { + IoReportTargetDeviceChangeAsynchronous(devObj, + pCustomNotify, + NULL, + NULL); + } + } + + delete[] pCustomNotify; + } + } +#endif + } + + return STATUS_SUCCESS; +} + +#pragma code_seg("PAGE") +NTSTATUS +SdcaXu_CreateCircuitModules( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit + ) +/*++ + +Routine Description: + + This routine creates all of the audio module elements and adds them to the circuit + +Return Value: + + NT status value + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + ACX_AUDIOMODULE_CALLBACKS audioModuleCallbacks; + ACX_AUDIOMODULE_CONFIG audioModuleCfg; + ACXAUDIOMODULE audioModuleElement; + PSDCAXU_AUDIOMODULE0_CONTEXT audioModule0Ctx; + PSDCAXU_AUDIOMODULE1_CONTEXT audioModule1Ctx; + PSDCAXU_AUDIOMODULE2_CONTEXT audioModule2Ctx; + ACX_PNPEVENT_CONFIG audioModuleEventCfg; + ACXPNPEVENT audioModuleEvent; + + PAGED_CODE(); + + // Now add audio modules to the circuit + // module 0 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand0; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule0Id; + audioModuleCfg.Descriptor.ClassId = AudioModule0Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(0,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE0_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE0_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE0DESCRIPTION, + wcslen(AUDIOMODULE0DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE0_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule0Ctx = GetSdcaXuAudioModule0Context(audioModuleElement); + ASSERT(audioModule0Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule0Ctx->Event = audioModuleEvent; + audioModule0Ctx->Circuit = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 1 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand1; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule1Id; + audioModuleCfg.Descriptor.ClassId = AudioModule1Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(0,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE1_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE1_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE1DESCRIPTION, + wcslen(AUDIOMODULE1DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE1_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule1Ctx = GetSdcaXuAudioModule1Context(audioModuleElement); + ASSERT(audioModule1Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule1Ctx->Event = audioModuleEvent; + audioModule1Ctx->Circuit = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 2 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand2; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule2Id; + audioModuleCfg.Descriptor.ClassId = AudioModule2Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE2_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE2_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE2DESCRIPTION, + wcslen(AUDIOMODULE2DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE2_CONTEXT); + attributes.ParentObject = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Circuit, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule2Ctx = GetSdcaXuAudioModule2Context(audioModuleElement); + ASSERT(audioModule2Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule2Ctx->Event = audioModuleEvent; + audioModule2Ctx->Circuit = Circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(Circuit, (ACXELEMENT *) &audioModuleElement, 1)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateRenderDevice( + _In_ WDFDEVICE Device, + _Out_ WDFDEVICE* RenderDevice +) +{ + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE renderDevice = NULL; + + PAGED_CODE(); + + auto exit = scope_exit([&status, &renderDevice]() { + if (!NT_SUCCESS(status)) + { + if (renderDevice != NULL) + { + WdfObjectDelete(renderDevice); + } + } + }); + + *RenderDevice = NULL; + + // + // Create a child audio device for this circuit. + // + PWDFDEVICE_INIT devInit = NULL; + devInit = WdfPdoInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == devInit, STATUS_INSUFFICIENT_RESOURCES); + + auto devInit_free = scope_exit([&devInit, &status]() { + WdfDeviceInitFree(devInit); + }); + + // + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddHardwareID(devInit, &RenderHardwareId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignDeviceID(devInit, &RenderDeviceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddCompatibleID(devInit, &RenderCompatibleId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignInstanceID(devInit, &RenderInstanceId)); + + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAssignContainerID(devInit, &RenderContainerId)); + + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + RETURN_NTSTATUS_IF_FAILED(WdfPdoInitAddDeviceText(devInit, + &RenderDeviceDescription, + &RenderDeviceLocation, + 0x409)); + + WdfPdoInitSetDefaultLocale(devInit, 0x409); + + // + // Allow ACX to add any pre-requirement it needs on this device. + // + ACX_DEVICEINIT_CONFIG acxDevInitCfg; + ACX_DEVICEINIT_CONFIG_INIT(&acxDevInitCfg); + acxDevInitCfg.Flags |= AcxDeviceInitConfigRawDevice; + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(devInit, &acxDevInitCfg)); + + // + // Initialize the pnpPowerCallbacks structure. Callback events for PNP + // and Power are specified here. If you don't supply any callbacks, + // the Framework will take appropriate default actions based on whether + // DeviceInit is initialized to be an FDO, a PDO or a filter device + // object. + // + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = SdcaXuR_EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = SdcaXuR_EvtDeviceReleaseHardware; + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = SdcaXuR_EvtDeviceSelfManagedIoInit; + WdfDeviceInitSetPnpPowerEventCallbacks(devInit, &pnpPowerCallbacks); + + // + // Specify a context for this render device. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_RENDER_DEVICE_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuR_EvtDeviceContextCleanup; + attributes.ExecutionLevel = WdfExecutionLevelPassive; + RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&devInit, &attributes, &renderDevice)); + + // + // devInit attached to device, no need to free + // + devInit_free.release(); + + // + // Tell the framework to set the NoDisplayInUI in the DeviceCaps so + // that the device does not show up in Device Manager. + // + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + pnpCaps.NoDisplayInUI = WdfTrue; + WdfDeviceSetPnpCapabilities(renderDevice, &pnpCaps); + + // + // Init render's device context. + // + PSDCAXU_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(renderDevice); + ASSERT(devCtx != NULL); + UNREFERENCED_PARAMETER(devCtx); + + // + // Allow ACX to add any post-requirement it needs on this device. + // + ACX_DEVICE_CONFIG devCfg; + ACX_DEVICE_CONFIG_INIT(&devCfg); + RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(renderDevice, &devCfg)); + + // + // Set output value. + // + *RenderDevice = renderDevice; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddDynamicRender( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Create a device to associated with this circuit. + // + WDFDEVICE renderDevice = NULL; + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateRenderDevice(Device, &renderDevice)); + auto deviceFree = scope_exit([&renderDevice]() { + WdfObjectDelete(renderDevice); + }); + + ASSERT(renderDevice); + PSDCAXU_RENDER_DEVICE_CONTEXT renderDevCtx; + renderDevCtx = GetRenderDeviceContext(renderDevice); + ASSERT(renderDevCtx); + + // + // Create a render circuit associated with this child device. + // + ACXCIRCUIT renderCircuit = NULL; + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateRenderCircuit(renderDevice, CircuitConfig, &renderCircuit)); + + renderDevCtx->Circuit = renderCircuit; + renderDevCtx->FirstTimePrepareHardware = TRUE; + + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateCircuitModules(Device, renderCircuit)); + + // + // Add circuit to device's dynamic circuit device list. + // + RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuitDevice(Device, renderDevice)); + + // Successfully created circuit for dynamic deivce + // Do not delete + deviceFree.release(); + + PSDCAXU_DEVICE_CONTEXT devCtx = GetSdcaXuDeviceContext(Device); + for (ULONG i = 0; i < ARRAYSIZE(devCtx->EndpointDevices); ++i) + { + if (devCtx->EndpointDevices[i].CircuitDevice == nullptr) + { + DrvLogInfo(g_SDCAVXuLog, FLAG_DDI, L"XU Device %p adding render circuit device %p with component ID %!GUID! and Uri %ls", + Device, renderDevice, &CircuitConfig->ComponentID, + CircuitConfig->ComponentUri.Buffer ? CircuitConfig->ComponentUri.Buffer : L"<none>"); + devCtx->EndpointDevices[i].CircuitDevice = renderDevice; + devCtx->EndpointDevices[i].CircuitId = CircuitConfig->ComponentID; + if (CircuitConfig->ComponentUri.Length > 0) + { + USHORT cbAlloc = CircuitConfig->ComponentUri.Length + sizeof(WCHAR); + // protect against overflow + if (CircuitConfig->ComponentUri.Length % 2 != 0 || + cbAlloc < CircuitConfig->ComponentUri.Length) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INVALID_PARAMETER); + } + + PWCHAR circuitUri = (PWCHAR)ExAllocatePool2(POOL_FLAG_NON_PAGED, cbAlloc, DRIVER_TAG); + if (!circuitUri) + { + RETURN_NTSTATUS_IF_FAILED(STATUS_INSUFFICIENT_RESOURCES); + } + + devCtx->EndpointDevices[i].CircuitUri.Buffer = circuitUri; + devCtx->EndpointDevices[i].CircuitUri.MaximumLength = cbAlloc; + devCtx->EndpointDevices[i].CircuitUri.Length = 0; + RtlCopyUnicodeString(&devCtx->EndpointDevices[i].CircuitUri, &CircuitConfig->ComponentUri); + } + break; + } + } + + return status; +} + +// {3CE41646-9BF2-4A9E-B851-D711CAE9AEA8} +DEFINE_GUID(SDCAVADPropsetId, + 0x3ce41646, 0x9bf2, 0x4a9e, 0xb8, 0x51, 0xd7, 0x11, 0xca, 0xe9, 0xae, 0xa8); + +typedef enum { + SDCAVAD_PROPERTY_TEST1, + SDCAVAD_PROPERTY_TEST2, + SDCAVAD_PROPERTY_TEST3, + SDCAVAD_PROPERTY_TEST4, + SDCAVAD_PROPERTY_TEST5, + SDCAVAD_PROPERTY_TEST6, +} SDCAVAD_Properties; + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_SDCAVADPropertyTest3( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(pValue); + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVXuLog, FLAG_STREAM, L"SDCAVXu: SDCAVAD_PROPERTY_TEST3"); + + *ValueCbOut = 0; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_SDCAVADPropertyTest4( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVXuLog, FLAG_STREAM, L"SDCAVXu: SDCAVAD_PROPERTY_TEST4"); + + *((PULONG)pValue) = 11; + *ValueCbOut = sizeof(ULONG); + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_SDCAVADPropertyTest5( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(pValue); + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVXuLog, FLAG_STREAM, L"SDCAVXu: SDCAVAD_PROPERTY_TEST5"); + + *ValueCbOut = 0; + + return status; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_SDCAVADPropertyTest6( + _Inout_ PVOID pValue, + _In_ ULONG ValueCb, + _Out_ PULONG ValueCbOut +) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ValueCb); + + NTSTATUS status = STATUS_SUCCESS; + + DrvLogInfo(g_SDCAVXuLog, FLAG_STREAM, L"SDCAVXu: SDCAVAD_PROPERTY_TEST6"); + + *((PULONG)pValue) = 13; + *ValueCbOut = sizeof(ULONG); + + return status; +} + +PAGED_CODE_SEG +VOID +SdcaXu_EvtPropertyCallback( + _In_ WDFOBJECT Object, + _In_ WDFREQUEST Request +) +{ + UNREFERENCED_PARAMETER(Object); + + PAGED_CODE(); + + ACX_REQUEST_PARAMETERS params; + ACX_REQUEST_PARAMETERS_INIT(¶ms); + + AcxRequestGetParameters(Request, ¶ms); + + NTSTATUS status = STATUS_SUCCESS; + PVOID Value = params.Parameters.Property.Value; + ULONG ValueCb = params.Parameters.Property.ValueCb; + ULONG ValueCbOut = 0; + + if (IsEqualGUID(params.Parameters.Property.Set, SDCAVADPropsetId)) + { + switch (params.Parameters.Property.Id) + { + case SDCAVAD_PROPERTY_TEST3: + status = SdcaXu_SDCAVADPropertyTest3(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST4: + status = SdcaXu_SDCAVADPropertyTest4(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST5: + status = SdcaXu_SDCAVADPropertyTest5(Value, ValueCb, &ValueCbOut); + break; + case SDCAVAD_PROPERTY_TEST6: + status = SdcaXu_SDCAVADPropertyTest6(Value, ValueCb, &ValueCbOut); + break; + default: + break; + } + } + + WdfRequestCompleteWithInformation(Request, status, ValueCbOut); +} + +static ACX_PROPERTY_ITEM CircuitProperties[] = +{ + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST3, + ACX_PROPERTY_ITEM_FLAG_SET, + SdcaXu_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST4, + ACX_PROPERTY_ITEM_FLAG_GET, + SdcaXu_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST5, + ACX_PROPERTY_ITEM_FLAG_SET, + SdcaXu_EvtPropertyCallback + }, + { + &SDCAVADPropsetId, + SDCAVAD_PROPERTY_TEST6, + ACX_PROPERTY_ITEM_FLAG_GET, + SdcaXu_EvtPropertyCallback + }, +}; + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig, + _Out_ ACXCIRCUIT *Circuit +) +/*++ + +Routine Description: + + This routine builds the SdcaXu render circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + // + // Get a CircuitInit structure. + // + PACXCIRCUIT_INIT circuitInit = NULL; + circuitInit = AcxCircuitInitAllocate(Device); + RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_MEMORY_NOT_ALLOCATED); + auto circuitInit_free = scope_exit([&circuitInit]() { + AcxCircuitInitFree(circuitInit); + }); + + // + // Init output value. + // + *Circuit = NULL; + + // + // Copy Circuit configuration + // + PSDCAXU_ACX_CIRCUIT_CONFIG pCircuitConfig = NULL; + pCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2(POOL_FLAG_NON_PAGED, + CircuitConfig->cbSize, + DRIVER_TAG); + RETURN_NTSTATUS_IF_TRUE(NULL == pCircuitConfig, STATUS_MEMORY_NOT_ALLOCATED); + auto circuitConfig_free = scope_exit([&pCircuitConfig]() { + ExFreePoolWithTag(pCircuitConfig, DRIVER_TAG); + }); + + RtlCopyMemory(pCircuitConfig, CircuitConfig, CircuitConfig->cbSize); + + // Remap UNICODE_STRING.Buffer + // buffer for unicode string begins immediately after SdcaXuAcxCircuitConfig + RETURN_NTSTATUS_IF_TRUE_MSG(pCircuitConfig->cbSize < (sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + pCircuitConfig->CircuitName.MaximumLength), + STATUS_INVALID_PARAMETER, L"CircuitConfig->cbSize = %d Required = %d", + pCircuitConfig->cbSize, + (int)(sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + pCircuitConfig->CircuitName.MaximumLength)); + + pCircuitConfig->CircuitName.Buffer = (PWCH)(pCircuitConfig + 1); + + // + // Create a circuit. + // + + // + // Add circuit identifiers. + // + if (!IsEqualGUID(pCircuitConfig->ComponentID, GUID_NULL)) + { + AcxCircuitInitSetComponentId(circuitInit, &pCircuitConfig->ComponentID); + } + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &pCircuitConfig->ComponentUri)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(circuitInit, &pCircuitConfig->CircuitName)); + + // + // Add circuit type. + // + AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeRender); + + // + // Assign the circuit's pnp-power callbacks. + // + { + ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks; + ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks); + powerCallbacks.EvtAcxCircuitPowerUp = SdcaXuR_EvtCircuitPowerUp; + powerCallbacks.EvtAcxCircuitPowerDown = SdcaXuR_EvtCircuitPowerDown; + AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks); + } + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback( + circuitInit, + SdcaXuR_EvtCircuitRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback( + circuitInit, + SdcaXuR_EvtCircuitCreateStream)); + + // + // Disable default Stream Bridge handling in ACX + // Create stream handler will add Stream Bridge + // to support Object-bag forwarding + // + AcxCircuitInitDisableDefaultStreamBridgeHandling(circuitInit); + + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit, + CircuitProperties, + SIZEOF_ARRAY(CircuitProperties))); + + // + // Create the circuit. + // + WDF_OBJECT_ATTRIBUTES attributes; + ACXCIRCUIT circuit; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_RENDER_CIRCUIT_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuR_EvtCircuitContextCleanup; + RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit)); + + // circuitInit is now associated with circuit and will be managed with + // circuit lifetime. + circuitInit_free.release(); + + SDCAXU_RENDER_CIRCUIT_CONTEXT *circuitCtx; + ASSERT(circuit != NULL); + circuitCtx = GetRenderCircuitContext(circuit); + ASSERT(circuitCtx); + +#ifdef ACX_WORKAROUND_AGGREGATED_MODULE_NOTIFICATIONS + // cache the parent device for later, unreferenced since + // this is the parent + circuitCtx->EndpointDevice = Device; +#endif + + circuitCtx->CircuitConfig = pCircuitConfig; + circuitConfig_free.release(); + + // + // Post circuit creation initialization. + // + + // + // Add two custom circuit elements. Note that driver doesn't need to + // perform this step if it doesn't want to expose any circuit elements. + // + + // + // Create 1st custom circuit-element. + // + ACX_ELEMENT_CONFIG elementCfg; + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + const int numElements = 2; + ACXELEMENT elements[numElements] = { 0 }; + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + SDCAXU_ELEMENT_CONTEXT* elementCtx; + elementCtx = GetSdcaXuElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom circuit-element. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = circuit; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetSdcaXuElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add the circuit elements + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements))); + + // + // Create render pin. AcxCircuit creates the other pin by default. + // + + ACX_PIN_CALLBACKS pinCallbacks; + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinSetDataFormat = SdcaXuR_EvtAcxPinSetDataFormat; + + ACX_PIN_CONFIG pinCfg; + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSink; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PIN_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + ACXPIN pin; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + SDCAXU_PIN_CONTEXT* pinCtx; + pinCtx = GetSdcaXuPinContext(pin); + ASSERT(pinCtx); + + // When the downstream pin connects to the Class driver, we'll + // copy formats from the Class driver (instead of hardcoding + // formats here) + + // + // Add render pin, using default pin id (0) + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + /////////////////////////////////////////////////////////// + // + // Create bridge pin. AcxCircuit creates the other pin by default. + // + ACX_PIN_CALLBACKS_INIT(&pinCallbacks); + pinCallbacks.EvtAcxPinConnected = SdcaXu_EvtPinConnected; + + ACX_PIN_CONFIG_INIT(&pinCfg); + pinCfg.Type = AcxPinTypeSource; + pinCfg.Communication = AcxPinCommunicationNone; + pinCfg.Category = &KSCATEGORY_AUDIO; + pinCfg.PinCallbacks = &pinCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PIN_CONTEXT); + attributes.EvtCleanupCallback = SdcaXuR_EvtPinContextCleanup; + attributes.ParentObject = circuit; + + pin = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin)); + + ASSERT(pin != NULL); + pinCtx = GetSdcaXuPinContext(pin); + ASSERT(pinCtx); + + // + // Add brige pin, using default pin id (1) + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1)); + + // + // Add a stream bridge to the bridge pin to propagate the stream obj-bags. + // + { + PCGUID inModes[] = + { + &NULL_GUID, // Match every mode. + }; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = pin; + + ACX_STREAM_BRIDGE_CONFIG streamBridgeConfig; + ACX_STREAM_BRIDGE_CONFIG_INIT(&streamBridgeConfig); + + streamBridgeConfig.Flags |= AcxStreamBridgeForwardInStreamVarArguments; + streamBridgeConfig.InModesCount = ARRAYSIZE(inModes); + streamBridgeConfig.InModes = inModes; + streamBridgeConfig.OutMode = &NULL_GUID; // Use the MODE associated the in-stream. + + ACXSTREAMBRIDGE streamBridge = NULL; + RETURN_NTSTATUS_IF_FAILED(AcxStreamBridgeCreate(circuit, &attributes, &streamBridgeConfig, &streamBridge)); + + RETURN_NTSTATUS_IF_FAILED(AcxPinAddStreamBridges(pin, &streamBridge, 1)); + } + + // + // Explicitly connect the circuit/elements. Note that driver doens't + // need to perform this step when circuit/elements are connected in the + // same order as they were added to the circuit. By default ACX connects + // the elements starting from the sink circuit pin and ending with the + // source circuit pin for both render and capture devices. + // + // circuit.pin[default_sink] -> 1st element.pin[default_in] + // 1st element.pin[default_out] -> 2nd element.pin[default_in] + // 2nd element.pin[default_out] -> circuit.pin[default_source] + // + const int numConnections = numElements + 1; + ACX_CONNECTION connections[numConnections]; + ACX_CONNECTION_INIT(&connections[0], circuit, elements[0]); + ACX_CONNECTION_INIT(&connections[1], elements[0], elements[1]); + ACX_CONNECTION_INIT(&connections[2], elements[1], circuit); + + // + // Add the connections linking circuit to elements. + // + RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(circuit, connections, SIZEOF_ARRAY(connections))); + + // + // Set output value. + // + *Circuit = circuit; + + return STATUS_SUCCESS; +} + +#pragma code_seg() +_Use_decl_annotations_ +NTSTATUS +SdcaXuR_EvtCircuitPowerUp ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE PreviousState + ) +{ + // Do not page out. + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(PreviousState); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +_Use_decl_annotations_ +NTSTATUS +SdcaXuR_EvtCircuitPowerDown ( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ WDF_POWER_DEVICE_STATE TargetState + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(Circuit); + UNREFERENCED_PARAMETER(TargetState); + + return STATUS_SUCCESS; +} + + +#pragma code_seg("PAGE") +NTSTATUS +SdcaXu_CreateStreamModules( + _In_ WDFDEVICE Device, + _In_ ACXSTREAM Stream + ) +/*++ + +Routine Description: + + This routine creates all of the audio module elements and adds them to the stream + +Return Value: + + NT status value + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + ACX_AUDIOMODULE_CALLBACKS audioModuleCallbacks; + ACX_AUDIOMODULE_CONFIG audioModuleCfg; + ACXAUDIOMODULE audioModuleElement; + PSDCAXU_AUDIOMODULE0_CONTEXT audioModule0Ctx; + PSDCAXU_AUDIOMODULE1_CONTEXT audioModule1Ctx; + PSDCAXU_AUDIOMODULE2_CONTEXT audioModule2Ctx; + ACX_PNPEVENT_CONFIG audioModuleEventCfg; + ACXPNPEVENT audioModuleEvent; + + PAGED_CODE(); + + // Now add audio modules to the circuit + // module 0 + // for simplicity of the example, we implement the same modules on the stream as is + // on the circuit + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand0; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule0Id; + audioModuleCfg.Descriptor.ClassId = AudioModule0Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE0_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE0_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE0DESCRIPTION, + wcslen(AUDIOMODULE0DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE0_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule0Ctx = GetSdcaXuAudioModule0Context(audioModuleElement); + ASSERT(audioModule0Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule0Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 1 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand1; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule1Id; + audioModuleCfg.Descriptor.ClassId = AudioModule1Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE1_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE1_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE1DESCRIPTION, + wcslen(AUDIOMODULE1DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE1_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule1Ctx = GetSdcaXuAudioModule1Context(audioModuleElement); + ASSERT(audioModule1Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule1Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + // module 2 + + ACX_AUDIOMODULE_CALLBACKS_INIT(&audioModuleCallbacks); + audioModuleCallbacks.EvtAcxAudioModuleProcessCommand = SdcaXu_EvtProcessCommand2; + + ACX_AUDIOMODULE_CONFIG_INIT(&audioModuleCfg); + audioModuleCfg.Name = &AudioModule2Id; + audioModuleCfg.Descriptor.ClassId = AudioModule2Id; + audioModuleCfg.Descriptor.InstanceId = AUDIOMODULE_INSTANCE_ID(1,0); + audioModuleCfg.Descriptor.VersionMajor = AUDIOMODULE2_MAJOR; + audioModuleCfg.Descriptor.VersionMinor = AUDIOMODULE2_MINOR; + RETURN_NTSTATUS_IF_FAILED(RtlStringCchCopyNW(audioModuleCfg.Descriptor.Name, + ACX_AUDIOMODULE_MAX_NAME_CCH_SIZE, + AUDIOMODULE2DESCRIPTION, + wcslen(AUDIOMODULE2DESCRIPTION))); + + audioModuleCfg.Callbacks = &audioModuleCallbacks; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_AUDIOMODULE2_CONTEXT); + attributes.ParentObject = Stream; + + RETURN_NTSTATUS_IF_FAILED(AcxAudioModuleCreate(Stream, &attributes, &audioModuleCfg, &audioModuleElement)); + + audioModule2Ctx = GetSdcaXuAudioModule2Context(audioModuleElement); + ASSERT(audioModule2Ctx); + + ACX_PNPEVENT_CONFIG_INIT(&audioModuleEventCfg); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_PNPEVENT_CONTEXT); + attributes.ParentObject = audioModuleElement; + RETURN_NTSTATUS_IF_FAILED(AcxPnpEventCreate(Device, audioModuleElement, &attributes, &audioModuleEventCfg, &audioModuleEvent)); + + audioModule2Ctx->Event = audioModuleEvent; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(Stream, (ACXELEMENT *) &audioModuleElement, 1)); + + return STATUS_SUCCESS; +} + + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_EvtCircuitCreateStream( + _In_ WDFDEVICE Device, + _In_ ACXCIRCUIT Circuit, + _In_ ACXPIN Pin, + _In_ PACXSTREAM_INIT StreamInit, + _In_ ACXDATAFORMAT StreamFormat, + _In_ const GUID * SignalProcessingMode, + _In_ ACXOBJECTBAG VarArguments +) +/*++ + +Routine Description: + + This routine create a stream for the specified circuit. + +Return Value: + + NT status value + +--*/ +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Pin); + UNREFERENCED_PARAMETER(SignalProcessingMode); + UNREFERENCED_PARAMETER(VarArguments); + + ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW)); + + PSDCAXU_RENDER_DEVICE_CONTEXT devCtx; + devCtx = GetRenderDeviceContext(Device); + ASSERT(devCtx != NULL); + + // + // Set circuit-callbacks. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback( + StreamInit, + SdcaXuR_EvtStreamRequestPreprocess, + (ACXCONTEXT)AcxRequestTypeAny, // dbg only + AcxRequestTypeAny, + NULL, + AcxItemIdNone)); + + /* + // + // Add properties, events and methods. + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit, + StreamProperties, + StreamPropertiesCount)); + */ + + // + // Init streaming callbacks. + // + ACX_STREAM_CALLBACKS streamCallbacks; + ACX_STREAM_CALLBACKS_INIT(&streamCallbacks); + streamCallbacks.EvtAcxStreamPrepareHardware = SdcaXu_EvtStreamPrepareHardware; + streamCallbacks.EvtAcxStreamReleaseHardware = SdcaXu_EvtStreamReleaseHardware; + streamCallbacks.EvtAcxStreamRun = SdcaXu_EvtStreamRun; + streamCallbacks.EvtAcxStreamPause = SdcaXu_EvtStreamPause; + streamCallbacks.EvtAcxStreamAssignDrmContentId = SdcaXu_EvtStreamAssignDrmContentId; + + RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks)); + + // + // Create the stream. + // + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_STREAM_CONTEXT); + attributes.EvtDestroyCallback = SdcaXu_EvtStreamDestroy; + ACXSTREAM stream; + RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream)); + + CRenderStreamEngine *streamEngine = NULL; + streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CRenderStreamEngine(stream, StreamFormat); + RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_MEMORY_NOT_ALLOCATED); + auto stream_scope = scope_exit([&streamEngine]() { + delete streamEngine; + }); + + SDCAXU_STREAM_CONTEXT *streamCtx; + streamCtx = GetSdcaXuStreamContext(stream); + ASSERT(streamCtx); + streamCtx->StreamEngine = (PVOID)streamEngine; + stream_scope.release(); + + // + // Post stream creation initialization. + // + + ACXELEMENT elements[2] = {0}; + ACX_ELEMENT_CONFIG elementCfg; + // + // Create 1st custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0])); + + ASSERT(elements[0] != NULL); + SDCAXU_ELEMENT_CONTEXT *elementCtx; + elementCtx = GetSdcaXuElementContext(elements[0]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Create 2nd custom stream-elements. + // + ACX_ELEMENT_CONFIG_INIT(&elementCfg); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SDCAXU_ELEMENT_CONTEXT); + attributes.ParentObject = stream; + + RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1])); + + ASSERT(elements[1] != NULL); + elementCtx = GetSdcaXuElementContext(elements[1]); + ASSERT(elementCtx); + UNREFERENCED_PARAMETER(elementCtx); + + // + // Add stream elements + // + RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements))); + + // + // Add stream modules + // + RETURN_NTSTATUS_IF_FAILED(SdcaXu_CreateStreamModules(Device, stream)); + + return STATUS_SUCCESS; +} + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddRenders( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig +) +{ + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + // + // Add dynamic render circuit using raw PDO + // + status = SdcaXu_AddDynamicRender(Device, CircuitConfig); + + return status; +} + + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.h new file mode 100644 index 00000000..72fd17cb --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/render.h @@ -0,0 +1,84 @@ +/*++ + +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: + + render.h + +Abstract: + + Contains structure definitions and function prototypes private to + the driver. + +Environment: + + Kernel mode + +--*/ + +#pragma once + +// +// Circuit's settings for raw PDO. +// +DECLARE_CONST_UNICODE_STRING(RenderDeviceId, L"SDCAVad\\ExtensionSpeaker"); +DECLARE_CONST_UNICODE_STRING(RenderHardwareId, L"SDCAVad\\ExtensionSpeaker"); +DECLARE_CONST_UNICODE_STRING(RenderInstanceId, L"00"); +DECLARE_CONST_UNICODE_STRING(RenderCompatibleId, SDCAVAD_COMPATIBLE_ID); +DECLARE_CONST_UNICODE_STRING(RenderContainerId, SDCAVAD_CONTAINER_ID); +DECLARE_CONST_UNICODE_STRING(RenderDeviceDescription, L"SDCAVad Speaker(Ext)"); +DECLARE_CONST_UNICODE_STRING(RenderDeviceLocation, L"SDCAVad Speaker"); + +PAGED_CODE_SEG +NTSTATUS +SdcaXuR_SetPowerPolicy( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateRenderDevice( + _In_ WDFDEVICE Device, + _Out_ WDFDEVICE *RenderDevice +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_AddDynamicRender( + _In_ WDFDEVICE Device +); + +PAGED_CODE_SEG +NTSTATUS +SdcaXu_CreateRenderCircuit( + _In_ WDFDEVICE Device, + _In_ PSDCAXU_ACX_CIRCUIT_CONFIG CircuitConfig, + _Out_ ACXCIRCUIT *Circuit +); + +// Render Device callbacks. + +EVT_WDF_DEVICE_PREPARE_HARDWARE SdcaXuR_EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE SdcaXuR_EvtDeviceReleaseHardware; +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT SdcaXuR_EvtDeviceSelfManagedIoInit; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXuR_EvtDeviceContextCleanup; + +// Render callbacks. + +EVT_WDF_OBJECT_CONTEXT_CLEANUP SdcaXuR_EvtCircuitContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST SdcaXuR_EvtCircuitRequestPreprocess; +EVT_ACX_CIRCUIT_CREATE_STREAM SdcaXuR_EvtCircuitCreateStream; +EVT_ACX_CIRCUIT_POWER_UP SdcaXuR_EvtCircuitPowerUp; +EVT_ACX_CIRCUIT_POWER_DOWN SdcaXuR_EvtCircuitPowerDown; +EVT_ACX_PIN_SET_DATAFORMAT SdcaXuR_EvtAcxPinSetDataFormat; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SdcaXuR_EvtPinContextCleanup; +EVT_ACX_OBJECT_PREPROCESS_REQUEST SdcaXuR_EvtStreamRequestPreprocess; + +#pragma code_seg() + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/resources.rc b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/resources.rc new file mode 100644 index 00000000..e2c18dd9 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/resources.rc @@ -0,0 +1,12 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "ACX v1.0 SDCAXu Audio Driver" +#define VER_INTERNALNAME_STR "SDCAVXu.sys" +#define VER_ORIGINALFILENAME_STR "SDCAVXu.sys" + +#include "common.ver" + diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.cpp new file mode 100644 index 00000000..1396480d --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.cpp @@ -0,0 +1,264 @@ +/*++ + + 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: + + StreamEngine.cpp + +Abstract: + + Virtual Streaming Engine - this module controls streaming logic for + the device. + +Environment: + + Kernel mode + +--*/ + +#include "private.h" +#include <devguid.h> +#include "stdunk.h" +#include <ks.h> +#include <mmsystem.h> +#include <ksmedia.h> +#include "trace.h" +#include "streamengine.h" + +#ifndef __INTELLISENSE__ +#include "streamengine.tmh" +#endif + +_Use_decl_annotations_ +PAGED_CODE_SEG +CStreamEngine::CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ) + : m_CurrentState(AcxStreamStateStop), + m_Stream(Stream), + m_StreamFormat(StreamFormat) +{ + PAGED_CODE(); + + KeQueryPerformanceCounter(&m_PerformanceCounterFrequency); +} + +PAGED_CODE_SEG +CStreamEngine::~CStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStatePause; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStateStop; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Pause() +{ + PAGED_CODE(); + + m_CurrentState = AcxStreamStatePause; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::Run() +{ + PAGED_CODE(); + + if (m_CurrentState != AcxStreamStatePause) + { + return STATUS_INVALID_STATE_TRANSITION; + } + + m_CurrentState = AcxStreamStateRun; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ) +{ + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DrmContentId); + UNREFERENCED_PARAMETER(DrmRights); + + // + // At this point the driver should enforce the new DrmRights. + // + // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP. + // + // 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 AcxDrmForwardContentToDeviceObject + // function to provide the system with the device object representing the + // downstream module. (If the two modules communicate through the downstream + // module's content handlers, the upstream module calls AcxDrmAddContentHandlers + // instead.) + // + // For more information, see MSDN's DRM Functions and Interfaces. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CStreamEngine::GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ) +{ + PAGED_CODE(); + + *FifoSize = 128; + *Delay = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ) + : CStreamEngine(Stream, StreamFormat) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CRenderStreamEngine::~CRenderStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + + // Add other init here. + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CRenderStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ) + : CStreamEngine(Stream, StreamFormat) +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +CCaptureStreamEngine::~CCaptureStreamEngine() +{ + PAGED_CODE(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::PrepareHardware() +{ + PAGED_CODE(); + + RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware()); + + RETURN_NTSTATUS_IF_FAILED(ReadRegistrySettings()); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReleaseHardware() +{ + PAGED_CODE(); + + return CStreamEngine::ReleaseHardware(); +} + +_Use_decl_annotations_ +PAGED_CODE_SEG +NTSTATUS +CCaptureStreamEngine::ReadRegistrySettings() +{ + PAGED_CODE(); + return STATUS_SUCCESS; +} diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.h b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.h new file mode 100644 index 00000000..61046693 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/SdcaVXu/streamengine.h @@ -0,0 +1,131 @@ +#pragma once + +#define HNSTIME_PER_MILLISECOND 10000 + +class CStreamEngine +{ +public: + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Run(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + Pause(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + AssignDrmContentId( + _In_ ULONG DrmContentId, + _In_ PACXDRMRIGHTS DrmRights + ); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + GetHWLatency( + _Out_ ULONG * FifoSize, + _Out_ ULONG * Delay + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + virtual + ~CStreamEngine(); + +protected: + ACX_STREAM_STATE m_CurrentState; + ACXSTREAM m_Stream; + ACXDATAFORMAT m_StreamFormat; + LARGE_INTEGER m_PerformanceCounterFrequency; +}; + +class CRenderStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CRenderStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CRenderStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + +protected: + // data section. +}; + +class CCaptureStreamEngine : public CStreamEngine +{ +public: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + CCaptureStreamEngine( + _In_ ACXSTREAM Stream, + _In_ ACXDATAFORMAT StreamFormat + ); + + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + ~CCaptureStreamEngine(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + PrepareHardware(); + + virtual + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReleaseHardware(); + +protected: + __drv_maxIRQL(PASSIVE_LEVEL) + PAGED_CODE_SEG + NTSTATUS + ReadRegistrySettings(); +}; + diff --git a/audio/SoundWire/Samples/SdcaVad/common/NewDelete.cpp b/audio/SoundWire/Samples/SdcaVad/common/NewDelete.cpp new file mode 100644 index 00000000..a9473364 --- /dev/null +++ b/audio/SoundWire/Samples/SdcaVad/common/NewDelete.cpp @@ -0,0 +1,149 @@ +/***************************************************************************** +* 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_ + +#include "NewDelete.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, DEFAULT_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) + { + ExFreePool(pVoid); + } +} + +/***************************************************************************** +* ::delete() +***************************************************************************** +* Sized Delete function. +*/ +void __cdecl operator delete +( + PVOID pVoid +) +{ + if (pVoid) + { + ExFreePool(pVoid); + } +} + + +/***************************************************************************** +* ::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) + { + ExFreePool(pVoid); + } +} + + +/***************************************************************************** +* ::delete() +***************************************************************************** +* Array Delete function. +*/ +void __cdecl operator delete[] +( + _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid +) +{ + if (pVoid) + { + ExFreePool(pVoid); + } +} +#endif//_NEW_DELETE_OPERATORS_ diff --git a/avstream/avscamera/DMFT/AvsCameraDMFT.cpp b/avstream/avscamera/DMFT/AvsCameraDMFT.cpp index e12cff65..01f915be 100644 --- a/avstream/avscamera/DMFT/AvsCameraDMFT.cpp +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.cpp @@ -14,11 +14,20 @@ CMultipinMft::CMultipinMft() : m_nRefCount( 0 ), m_InputPinCount( 0 ), m_OutputPinCount( 0 ), - m_dwWorkQueueId ( MFASYNC_CALLBACK_QUEUE_MULTITHREADED ), - m_lWorkQueuePriority ( 0 ), - m_spAttributes( nullptr ), + m_StreamingState( DeviceStreamState_Disabled ), + m_OutPins(), + m_InPins(), + m_critSec(), + m_spDeviceManagerUnk( nullptr ), m_spSourceTransform( nullptr ), - m_SymbolicLink(nullptr) + m_eShutdownStatus( MFSHUTDOWN_INITIATED ), + m_dwWorkQueueId( MFASYNC_CALLBACK_QUEUE_MULTITHREADED ), + m_lWorkQueuePriority( 0 ), + m_punValue( 0 ), + m_spIkscontrol( nullptr ), + m_spAttributes( nullptr ), + m_outputPinMap(), + m_SymbolicLink( nullptr ) { HRESULT hr = S_OK; @@ -189,7 +198,7 @@ IFACEMETHODIMP CMultipinMft::InitializeTransform ( // // Create one on one mapping // - for (ULONG ulIndex = 0; ulIndex < m_InPins.size(); ulIndex++) + for (ULONG ulIndex = 0; ulIndex < (ULONG)(m_InPins.size()); ulIndex++) { ComPtr<CInPin> spInPin = (CInPin*)m_InPins[ulIndex].Get(); @@ -378,12 +387,16 @@ IFACEMETHODIMP CMultipinMft::GetInputAvailableType( ) { HRESULT hr = S_OK; - + + if (ppMediaType) + { + *ppMediaType = nullptr; + } + ComPtr<CInPin> spiPin = GetInPin( dwInputStreamID ); DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); DMFTCHECKNULL_GOTO( spiPin, done, MF_E_INVALIDSTREAMNUMBER ); - - *ppMediaType = nullptr; + hr = spiPin->GetOutputAvailableType( dwTypeIndex,ppMediaType ); @@ -417,12 +430,15 @@ IFACEMETHODIMP CMultipinMft::GetOutputAvailableType( CAutoLock Lock(m_critSec); ComPtr<COutPin> spoPin = GetOutPin( dwOutputStreamID ); + + if (ppMediaType) + { + *ppMediaType = nullptr; + } DMFTCHECKNULL_GOTO( spoPin.Get(), done, MF_E_INVALIDSTREAMNUMBER ); DMFTCHECKNULL_GOTO(ppMediaType, done, E_INVALIDARG); - *ppMediaType = nullptr; - hr = spoPin->GetOutputAvailableType( dwTypeIndex, ppMediaType ); if ( FAILED( hr ) ) diff --git a/avstream/avscamera/DMFT/AvsCameraDMFT.h b/avstream/avscamera/DMFT/AvsCameraDMFT.h index 27b8607b..d5c26f5a 100644 --- a/avstream/avscamera/DMFT/AvsCameraDMFT.h +++ b/avstream/avscamera/DMFT/AvsCameraDMFT.h @@ -226,11 +226,6 @@ public: static HRESULT CreateInstance( REFIID iid, void **ppMFT); - - __inline BOOL isPhotoModePhotoSequence() - { - return m_PhotoModeIsPhotoSequence; - } __inline DWORD GetQueueId() { @@ -305,11 +300,9 @@ protected: private: ULONG m_InputPinCount; ULONG m_OutputPinCount; - ULONG m_CustomPinCount; DeviceStreamState m_StreamingState; CBasePinArray m_OutPins; CBasePinArray m_InPins; - BOOL m_PhotoModeIsPhotoSequence; // used to store if the filter is in photo sequence or not long m_nRefCount; // Reference count CCritSec m_critSec; // Control lock.. taken only durign state change operations ComPtr <IUnknown> m_spDeviceManagerUnk; // D3D Manager set, when MFT_MESSAGE_SET_D3D_MANAGER is called through ProcessMessage diff --git a/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp b/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp index 4a4c75fc..4359b1ec 100644 --- a/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp +++ b/avstream/avscamera/DMFT/AvsCameraDMFTutils.cpp @@ -734,7 +734,9 @@ HRESULT ParseMetadata_FaceDetection( { return E_UNEXPECTED; } - PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1); + PMETADATA_FACEDATA pFaceData = reinterpret_cast<PMETADATA_FACEDATA>( + reinterpret_cast<BYTE*>(pFaceHeader) + sizeof(CAMERA_METADATA_FACEHEADER)); + UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count)); BYTE* pRectBuf = new (std::nothrow) BYTE[cbRectSize]; if (pRectBuf == NULL) diff --git a/avstream/avscamera/DMFT/basepin.h b/avstream/avscamera/DMFT/basepin.h index 8051188a..5b20e25e 100644 --- a/avstream/avscamera/DMFT/basepin.h +++ b/avstream/avscamera/DMFT/basepin.h @@ -90,11 +90,16 @@ public: _Out_opt_ ULONG* pBytesReturned ) { - UNREFERENCED_PARAMETER(pBytesReturned); - UNREFERENCED_PARAMETER(ulDataLength); - UNREFERENCED_PARAMETER(pMethodData); UNREFERENCED_PARAMETER(pMethod); UNREFERENCED_PARAMETER(ulMethodLength); + UNREFERENCED_PARAMETER(pMethodData); + UNREFERENCED_PARAMETER(ulDataLength); + + // Ensure *pBytesReturned is initialized if provided + if (pBytesReturned != nullptr) + { + *pBytesReturned = 0; + } return S_OK; } @@ -106,11 +111,16 @@ public: _Out_opt_ ULONG* pBytesReturned ) { - UNREFERENCED_PARAMETER(pBytesReturned); - UNREFERENCED_PARAMETER(ulDataLength); - UNREFERENCED_PARAMETER(pEventData); UNREFERENCED_PARAMETER(pEvent); UNREFERENCED_PARAMETER(ulEventLength); + UNREFERENCED_PARAMETER(pEventData); + UNREFERENCED_PARAMETER(ulDataLength); + + // Ensure *pBytesReturned is initialized if provided + if (pBytesReturned != nullptr) + { + *pBytesReturned = 0; + } return S_OK; } diff --git a/avstream/avscamera/sys/Capture.cpp b/avstream/avscamera/sys/Capture.cpp index 730370e6..3694716b 100644 --- a/avstream/avscamera/sys/Capture.cpp +++ b/avstream/avscamera/sys/Capture.cpp @@ -1462,7 +1462,7 @@ Return Value: // if( Pin->DeviceState == KSSTATE_STOP ) { - if( !CapPin->CaptureBitmapInfoHeader( ) ) + if( !NT_SUCCESS(CapPin->CaptureBitmapInfoHeader( )) ) { Status = STATUS_INSUFFICIENT_RESOURCES; } diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp index 38d4f555..ec969554 100644 --- a/avstream/avscamera/sys/Device.cpp +++ b/avstream/avscamera/sys/Device.cpp @@ -45,6 +45,8 @@ CCaptureDevice ( , m_FilterDescriptorCount(0) , m_Sensor(nullptr) , m_Context(nullptr) + , m_DmaAdapterObject(nullptr) + , m_NumberOfMapRegisters(0) { PAGED_CODE(); } @@ -85,9 +87,10 @@ CCaptureDevice:: GetFilterIndex(PKSFILTER Filter) { PAGED_CODE(); + ULONG i; - for( i=0; i<m_FilterDescriptorCount; i++ ) + for( i=0; i<(ULONG)m_FilterDescriptorCount; i++ ) { if( Filter->Descriptor->ReferenceGuid && IsEqualGUID(*(m_Context[i].Descriptor->ReferenceGuid), *Filter->Descriptor->ReferenceGuid)) @@ -130,13 +133,19 @@ QueryForInterface( _In_ USHORT Size, _In_ USHORT Version, _In_opt_ PVOID InterfaceSpecificData - ) +) { PAGED_CODE(); PIRP pIrp; NTSTATUS status; + // Ensure the output parameter is initialized to a known state. + if (Interface) + { + RtlZeroMemory(Interface, Size); + } + if (TopOfStack == nullptr) { return STATUS_INVALID_PARAMETER; @@ -181,7 +190,7 @@ QueryForInterface( KernelMode, FALSE, // Not alertable NULL - ); + ); status = pIrp->IoStatus.Status; } @@ -192,6 +201,12 @@ QueryForInterface( status = STATUS_INSUFFICIENT_RESOURCES; } + // If the call failed, ensure Interface is zeroed to avoid returning uninitialized memory. + if (!NT_SUCCESS(status) && Interface) + { + RtlZeroMemory(Interface, Size); + } + return status; } diff --git a/avstream/avscamera/sys/Device.h b/avstream/avscamera/sys/Device.h index c203f70e..8aec7cf4 100644 --- a/avstream/avscamera/sys/Device.h +++ b/avstream/avscamera/sys/Device.h @@ -71,7 +71,7 @@ protected: // // Number of Filter descriptors & filter factories. - size_t m_FilterDescriptorCount; + ULONG m_FilterDescriptorCount; // Pointer to an array of filter descriptor pointers. // Typically it's one sensor for each filter factory. @@ -407,6 +407,7 @@ public: static IO_COMPLETION_ROUTINE IrpSynchronousCompletion; virtual + _Must_inspect_result_ NTSTATUS QueryForInterface( _In_ PDEVICE_OBJECT TopOfStack, diff --git a/avstream/avscamera/sys/PreviewHwSim.cpp b/avstream/avscamera/sys/PreviewHwSim.cpp index f55ffa20..66740572 100644 --- a/avstream/avscamera/sys/PreviewHwSim.cpp +++ b/avstream/avscamera/sys/PreviewHwSim.cpp @@ -209,8 +209,8 @@ Return Value: 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); + PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)((PUCHAR)pStreamHeader + sizeof(KSSTREAM_HEADER)); + PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO)((PUCHAR)pFrameInfo + sizeof(KS_FRAME_INFO)); ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize; if(m_PhotoConfirmationEntry.isRequired()) @@ -325,7 +325,7 @@ Return Value: } else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION)) { - m_Illuminated = !m_Illuminated; + m_Illuminated = ~m_Illuminated; if (m_Illuminated) { pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON; diff --git a/avstream/avscamera/sys/Roi.cpp b/avstream/avscamera/sys/Roi.cpp index e1118996..b269b332 100644 --- a/avstream/avscamera/sys/Roi.cpp +++ b/avstream/avscamera/sys/Roi.cpp @@ -143,7 +143,7 @@ Return Value: // We assume the controls have been validated first. PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL pIspCtrl = - reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL> (this+1); + reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL>(reinterpret_cast<PBYTE>(this) + sizeof(CRoiProperty)); // Loop thru the controls. for( ULONG i=0; i<m_Hdr.ControlCount; i++ ) @@ -155,6 +155,11 @@ Return Value: // Advance to the next control. pIspCtrl = NextCtrl( pIspCtrl ); + if(pIspCtrl == nullptr) + { + NT_ASSERTMSG("NextCtrl( pCtrl ) returned 0! Should never happen!", FALSE); + return nullptr; + } } return nullptr; @@ -192,13 +197,18 @@ Return Value: { // We assume the controls have been validated first. PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL pIspCtrl = - reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL> (this+1); + reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL>(reinterpret_cast<PBYTE>(this) + sizeof(CRoiProperty)); // Loop thru all the controls. for( ULONG i=0; i<m_Hdr.ControlCount; i++ ) { // Advance to the next control. pIspCtrl = NextCtrl( pIspCtrl ); + if (pIspCtrl == nullptr) + { + NT_ASSERTMSG("NextCtrl( pCtrl ) returned 0! Should never happen!", FALSE); + return nullptr; + } } ULONG SizeToCopy = ::GetSize(pCtrl); @@ -277,14 +287,14 @@ Return Value: } PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL pIspCtrl = - reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL> (this+1); + reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_ISPCONTROL>(reinterpret_cast<BYTE*>(this) + sizeof(*this)); // Loop thru the controls. for( ULONG i=0; i<m_Hdr.ControlCount; i++ ) { // Make sure there is room to inspect this control - if( Size < ByteDiffPtrs( this, pIspCtrl+1 ) || - m_Hdr.Size < ByteDiffPtrs( &m_Hdr, pIspCtrl+1 ) ) + if( Size < ByteDiffPtrs( this, reinterpret_cast<PBYTE>(pIspCtrl) + sizeof(*pIspCtrl) ) || + m_Hdr.Size < ByteDiffPtrs( &m_Hdr, reinterpret_cast<PBYTE>(pIspCtrl) + sizeof(*pIspCtrl) ) ) { //NT_ASSERT(FALSE); DBG_TRACE( "Failed(1): Size=%d, should be at least %Iu", Size, ByteDiffPtrs( this, pIspCtrl+1 ) ); @@ -324,7 +334,7 @@ Return Value: // Index into to the control's ROI list. Get the equivilent of "pIspCtrl->RoiInfo[j]" PKSCAMERA_EXTENDEDPROP_ROI_INFO pRoiInfo = reinterpret_cast<PKSCAMERA_EXTENDEDPROP_ROI_INFO> - (((PBYTE) (pIspCtrl+1)) + (j * GetSizeOfRoiInfo(pIspCtrl->ControlId) )); + ((reinterpret_cast<PBYTE>(pIspCtrl) + sizeof(*pIspCtrl)) + (j * GetSizeOfRoiInfo(pIspCtrl->ControlId) )); // Validate the cooridinates if( pRoiInfo->Region.top < (LONG) TO_Q31(0) || @@ -500,6 +510,11 @@ Log() // Advance to the next control. pIspCtrl = reinterpret_cast<CRoiIspControl *>( NextCtrl( pIspCtrl ) ) ; + if (pIspCtrl == nullptr) + { + NT_ASSERTMSG("NextCtrl( pCtrl ) returned 0! Should never happen!", FALSE); + return; + } } } diff --git a/avstream/avscamera/sys/Roi.h b/avstream/avscamera/sys/Roi.h index 5149bf24..50dc03a5 100644 --- a/avstream/avscamera/sys/Roi.h +++ b/avstream/avscamera/sys/Roi.h @@ -208,18 +208,20 @@ public: class CWhiteBalanceRoiIspControl : public CRoiIspControl { private: - KSCAMERA_EXTENDEDPROP_ROI_WHITEBALANCE ROI[MAX_ROI]; + KSCAMERA_EXTENDEDPROP_ROI_WHITEBALANCE ROI[MAX_ROI] = {}; public: CWhiteBalanceRoiIspControl( _In_ CRoiProperty *pRoiProperty ) + : ROI{} { Init( pRoiProperty, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE ); } CWhiteBalanceRoiIspControl() : CRoiIspControl( KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE ) + , ROI{} {} ULONGLONG @@ -232,18 +234,20 @@ public: class CExposureRoiIspControl : public CRoiIspControl { private: - KSCAMERA_EXTENDEDPROP_ROI_EXPOSURE ROI[MAX_ROI]; + KSCAMERA_EXTENDEDPROP_ROI_EXPOSURE ROI[MAX_ROI] = {}; public: CExposureRoiIspControl( _In_ CRoiProperty *pRoiProperty ) + : ROI{} { Init( pRoiProperty, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE ); } CExposureRoiIspControl() : CRoiIspControl( KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE ) + , ROI{} {} ULONGLONG @@ -256,18 +260,20 @@ public: class CFocusRoiIspControl : public CRoiIspControl { private: - KSCAMERA_EXTENDEDPROP_ROI_FOCUS ROI[MAX_ROI]; + KSCAMERA_EXTENDEDPROP_ROI_FOCUS ROI[MAX_ROI] = {}; public: CFocusRoiIspControl( _In_ CRoiProperty *pRoiProperty ) + : ROI{} { Init( pRoiProperty, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ); } CFocusRoiIspControl() : CRoiIspControl( KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE ) + , ROI{} {} ULONGLONG diff --git a/avstream/avscamera/sys/Synthesizer.h b/avstream/avscamera/sys/Synthesizer.h index 7281ff80..94506b1d 100644 --- a/avstream/avscamera/sys/Synthesizer.h +++ b/avstream/avscamera/sys/Synthesizer.h @@ -231,6 +231,8 @@ public: , m_CommitCount(0) , m_CommitTime(0) , m_Rotation(AcpiPldRotation0) + , m_Colors(nullptr) + , m_StartTime(0) { m_Length = Height * m_SynthesisStride; KeQueryPerformanceCounter(&m_Frequency).QuadPart; diff --git a/avstream/avscamera/sys/VideoHwSim.cpp b/avstream/avscamera/sys/VideoHwSim.cpp index 839af530..64d14095 100644 --- a/avstream/avscamera/sys/VideoHwSim.cpp +++ b/avstream/avscamera/sys/VideoHwSim.cpp @@ -51,8 +51,12 @@ 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); + PKS_FRAME_INFO pFrameInfo = reinterpret_cast<PKS_FRAME_INFO>( + reinterpret_cast<PUCHAR>(pStreamHeader) + sizeof(KSSTREAM_HEADER) + ); + PKSSTREAM_METADATA_INFO pMetadata = reinterpret_cast<PKSSTREAM_METADATA_INFO>( + reinterpret_cast<PUCHAR>(pFrameInfo) + sizeof(KS_FRAME_INFO) + ); ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize; // TODO: This metadata should only be exposed on a sensor category preview pin. @@ -80,7 +84,7 @@ EmitMetadata( } else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION)) { - m_Illuminated = !m_Illuminated; + m_Illuminated = ~m_Illuminated; if (m_Illuminated) { pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON; diff --git a/avstream/avscamera/sys/filter.cpp b/avstream/avscamera/sys/filter.cpp index dfb6ce1f..93fa1de3 100644 --- a/avstream/avscamera/sys/filter.cpp +++ b/avstream/avscamera/sys/filter.cpp @@ -65,6 +65,7 @@ Return Value: m_pPerFrameSettings(nullptr), m_pinArray(nullptr), m_pMinimumRequestedFrames(nullptr), + m_PFSSize(0), // <-- Fix: Initialize m_PFSSize to 0 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 ), @@ -78,9 +79,9 @@ Return Value: m_ThumbnailNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTHUMBNAIL ), m_WarmStartNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART ), m_RoiNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL ), - m_ProfileNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE ) + m_ProfileNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE ), + m_Sensor(nullptr) { - PAGED_CODE(); DBG_ENTER("(Filter=%p)", Filter); @@ -2443,7 +2444,7 @@ Return Value: pSettings[i] = pSettings[0]; } - while( ((pFrame+1)<=pEnd) ) + while( ((((LPBYTE)pFrame) + pFrame->Size)<=pEnd) ) { PKSCAMERA_PERFRAMESETTING_FRAME_HEADER pNextFrame = (PKSCAMERA_PERFRAMESETTING_FRAME_HEADER) diff --git a/avstream/avscamera/sys/hwsim.cpp b/avstream/avscamera/sys/hwsim.cpp index 80a4adcf..8d76ef18 100644 --- a/avstream/avscamera/sys/hwsim.cpp +++ b/avstream/avscamera/sys/hwsim.cpp @@ -122,6 +122,7 @@ CHardwareSimulation ( , m_LastReportedExposureTime(DEF_EXPOSURE_TIME) // Assume the default exposure time for now. , m_LastReportedWhiteBalance(0) , m_FaceDetectionDelay(1) // Start out reporting immediately. + , m_LastFaceDetect() /*++ @@ -778,8 +779,8 @@ 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); + PKS_FRAME_INFO pFrameInfo = reinterpret_cast<PKS_FRAME_INFO>(reinterpret_cast<PUCHAR>(pStreamHeader) + sizeof(KSSTREAM_HEADER)); + PKSSTREAM_METADATA_INFO pMetadata = reinterpret_cast<PKSSTREAM_METADATA_INFO>(reinterpret_cast<PUCHAR>(pFrameInfo) + sizeof(KS_FRAME_INFO)); //PBYTE pData = (PBYTE) pMetadata->SystemVa; //ULONG BytesLeft = pMetadata->BufferSize; @@ -961,7 +962,7 @@ Return Value: m_LastFaceDetect.Flags &= Flags; PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1); - PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO) (pFrameInfo + 1); + PKSSTREAM_METADATA_INFO pMetadata = reinterpret_cast<PKSSTREAM_METADATA_INFO>(reinterpret_cast<PUCHAR>(pFrameInfo) + sizeof(KS_FRAME_INFO)); ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize; // Write Face Detection Info here diff --git a/avstream/avscamera/sys/imagehwsim.cpp b/avstream/avscamera/sys/imagehwsim.cpp index 2ba44721..6f73b71f 100644 --- a/avstream/avscamera/sys/imagehwsim.cpp +++ b/avstream/avscamera/sys/imagehwsim.cpp @@ -51,6 +51,14 @@ CImageHardwareSimulation ( , m_GlobalFrameNumber(0) , m_bEndOfSequence(FALSE) , m_PastBufferCount(0) // Zero only when the simulation inits. + , m_FlashStatus(0) + , m_PinMode(PinNormalMode) + , m_bFlashed(FALSE) + , m_bPastBufferTrigger(FALSE) + , m_pClone(nullptr) + , m_TriggerTime(0) + , m_bTriggered(FALSE) + , m_szwFramePath(nullptr) /*++ @@ -678,7 +686,7 @@ Return Value: 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); + PKSSTREAM_METADATA_INFO pMetadata = reinterpret_cast<PKSSTREAM_METADATA_INFO>(reinterpret_cast<BYTE*>(pFrameInfo) + sizeof(KS_FRAME_INFO)); PCAMERA_METADATA_IMAGEAGGREGATION pAggregation = (PCAMERA_METADATA_IMAGEAGGREGATION) (((PBYTE) pMetadata->SystemVa) + pMetadata->UsedSize); ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize; diff --git a/exclusions.csv b/exclusions.csv index 63d5e24a..0cae0380 100644 --- a/exclusions.csv +++ b/exclusions.csv @@ -1,13 +1,20 @@ -Path,Configurations,MinBuild,MaxBuild,Reason -audio\acx\samples\audiocodec\driver,*,,22621,Only NI: error C1083: Cannot open include file: 'acx.h': No such file or directory -general\dchu\osrfx2_dchu_extension_loose,*|x64,,22621,Only NI: Only x64: Fails to build -general\dchu\osrfx2_dchu_extension_tight,*|x64,,22621,Only NI: Only x64: Fails to build -network\trans\WFPSampler,Debug|ARM64,,22621,Only NI: Only ARM: Fails to build on EWDK 22621 with VS 17.1.5 - CallingConvention=StdCall not supported -prm,*,,22621,Only NI: Not supported on NI. -powerlimit\plclient,*,,22621,Only NI: Not supported on NI. -powerlimit\plpolicy,*,,22621,Only NI: Not supported on NI. -general\pcidrv,*,,26100,"failure introduced in VS17.14, suppressed until fix" -serial\serial,*,,26100,"failure introduced in VS17.14, suppressed until fix" -network\wlan\wdi,*,,26100,"failure introduced in VS17.14, suppressed until fix" -tools\kasan\samples\kasandemo-wdm,*|x64,,26100,"failure introduced in VS17.14, suppressed until fix" - +Path,Configurations,MinBuild,MaxBuild,MinNtTargetVersion,MaxNtTargetVersion,Reason +audio\acx\samples\audiocodec\driver,*,,22621,,,Only NI: error C1083: Cannot open include file: 'acx.h': No such file or directory +general\dchu\osrfx2_dchu_extension_loose,*|x64,,22621,,,Only NI: Only x64: Fails to build +general\dchu\osrfx2_dchu_extension_tight,*|x64,,22621,,,Only NI: Only x64: Fails to build +network\trans\WFPSampler,Debug|ARM64,,22621,,,Only NI: Only ARM: Fails to build on EWDK 22621 with VS 17.1.5 - CallingConvention=StdCall not supported +prm,*,,22621,,,Only NI: Not supported on NI. +powerlimit\plclient,*,,22621,,,Only NI: Not supported on NI. +powerlimit\plpolicy,*,,22621,,,Only NI: Not supported on NI. +general\pcidrv,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +serial\serial,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +network\wlan\wdi,*,26100,,,,"failure introduced in VS17.14, suppressed until fix" +tools\kasan\samples\kasandemo-wdm,*|x64,26100,,,,"failure introduced in VS17.14, suppressed until fix" +audio\sysvad,*,,,,22000,_NT_TARGET_VERSION: KSJACK_DESCRIPTION3 undeclared; audio jack descriptor v3 was added in 22H2 (10.0.22621) +network\netadaptercx\netvadapter,*,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) +network\wlan\wificx,*,,,,22621,_NT_TARGET_VERSION: requests an NDIS/DDI version newer than the linked library (C1189 wrong NDIS or DDI version) +powerlimit\plclient,*,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) +powerlimit\plpolicy,*,,,,22621,_NT_TARGET_VERSION: POWER_LIMIT_ATTRIBUTES not declared in the older library (C2061) +storage\class\classpnp,Debug|*,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only +storage\miniports\storahci,Debug|*,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug only +storage\msdsm,Debug|x64,,,,22621,_NT_TARGET_VERSION: STOR_ADDRESS_TYPE_NVME undeclared in the older library (C2065); Debug|x64 only diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index 78bbbfbb..dee4adb3 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -22,7 +22,6 @@ <VCProjectVersion>15.0</VCProjectVersion> <ProjectGuid>{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}</ProjectGuid> <RootNamespace>MediaSource</RootNamespace> - <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> <ProjectName>SimpleMediaSource</ProjectName> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> @@ -99,7 +98,7 @@ <EnablePREfast>false</EnablePREfast> <ExceptionHandling>Sync</ExceptionHandling> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <LanguageStandard>stdcpp17</LanguageStandard> + <LanguageStandard>stdcpp20</LanguageStandard> <PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> @@ -119,7 +118,7 @@ <EnablePREfast>false</EnablePREfast> <ExceptionHandling>Sync</ExceptionHandling> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <LanguageStandard>stdcpp17</LanguageStandard> + <LanguageStandard>stdcpp20</LanguageStandard> <PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> @@ -141,7 +140,7 @@ <EnablePREfast>false</EnablePREfast> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <ExceptionHandling>Sync</ExceptionHandling> - <LanguageStandard>stdcpp17</LanguageStandard> + <LanguageStandard>stdcpp20</LanguageStandard> <PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> @@ -165,7 +164,7 @@ <EnablePREfast>false</EnablePREfast> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <ExceptionHandling>Sync</ExceptionHandling> - <LanguageStandard>stdcpp17</LanguageStandard> + <LanguageStandard>stdcpp20</LanguageStandard> <PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp index 8ff15872..e672c9da 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp @@ -27,11 +27,11 @@ namespace winrt::WindowsSample::implementation RETURN_IF_FAILED(m_streamList[i]->Initialize(this, i, MFSampleAllocatorUsage_UsesProvidedAllocator)); RETURN_IF_FAILED(m_streamList[i]->GetStreamDescriptor(&streamDescriptorList[i])); - } + } - RETURN_IF_FAILED(MFCreatePresentationDescriptor(m_streamList.size(), streamDescriptorList.get(), &m_spPresentationDescriptor)); + RETURN_IF_FAILED(MFCreatePresentationDescriptor(static_cast<DWORD>(m_streamList.size()), streamDescriptorList.get(), &m_spPresentationDescriptor)); - m_sourceState = SourceState::Stopped; + m_sourceState = SourceState::Stopped; return S_OK; } diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj index cca6b63a..7eaf2747 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.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|x64"> @@ -59,7 +59,6 @@ <Configuration>Debug</Configuration> <Platform Condition="'$(Platform)' == ''">x64</Platform> <RootNamespace>SimpleMediaSourceDriver</RootNamespace> - <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion> </PropertyGroup> <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> @@ -128,6 +127,7 @@ <WppEnabled>true</WppEnabled> <WppRecorderEnabled>true</WppRecorderEnabled> <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData> + <LanguageStandard>stdcpp20</LanguageStandard> </ClCompile> <Link> <AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies> diff --git a/network/config/bindview/BINDING.CPP b/network/config/bindview/BINDING.CPP index b3771004..460d2f3c 100644 --- a/network/config/bindview/BINDING.CPP +++ b/network/config/bindview/BINDING.CPP @@ -10,7 +10,7 @@ // o How to enumerate binding interfaces. // o How to enable/disable bindings. // -// Notes: +// Notes: // // Author: Alok Sinha 15-May-01 // @@ -183,7 +183,7 @@ VOID WriteBindingPath (FILE *fp, fwprintf( fp, L"\n%s", lpszName ); } } - + ReleaseRef( pencbp ); } else { @@ -389,7 +389,7 @@ VOID ListBindings (INetCfgComponent *pncc, HTREEITEM hTreeItem; ULONG ulIndex; HRESULT hr; - + hr = HrGetBindingPathEnum( pncc, EBP_BELOW, &pencbp ); @@ -429,7 +429,7 @@ VOID ListBindings (INetCfgComponent *pncc, ulIndex++; } - + ReleaseRef( pencbp ); } else { @@ -533,7 +533,7 @@ VOID ListInterfaces (INetCfgBindingPath *pncbp, // // Function: HandleBindingPathOperation // -// Purpose: +// Purpose: // // Arguments: // hwndOwner [in] Owner window. @@ -778,7 +778,7 @@ FindBindingPath ( &pncc ); if ( hr == S_OK ) { - + hr = HrGetBindingPathEnum( pncc, EBP_BELOW, &pencbp ); diff --git a/network/config/bindview/BINDVIEW.CPP b/network/config/bindview/BINDVIEW.CPP index 4231f7c4..dbd26fb5 100644 --- a/network/config/bindview/BINDVIEW.CPP +++ b/network/config/bindview/BINDVIEW.CPP @@ -1444,7 +1444,7 @@ VOID ShowComponentMenu (HWND hwndOwner, LPARAM lParam) { ULONG ulSelection; - POINT pt; + POINT pt{}; GetCursorPos( &pt ); ulSelection = (ULONG)TrackPopupMenu( hComponentSubMenu, @@ -1496,7 +1496,7 @@ VOID ShowBindingPathMenu (HWND hwndOwner, { MENUITEMINFOW menuItemInfo; ULONG ulSelection; - POINT pt; + POINT pt{}; // // Build the shortcut menu depending on whether path is @@ -1563,7 +1563,7 @@ VOID ShowBindingPathMenu (HWND hwndOwner, // lpdwItemType [out] Type, binding path or network component. // fEnabled [out] TRUE if the binding path or component is enabled. // -// Returns: TRUE on sucess. +// Returns: TRUE on success. // // Notes: // @@ -1787,7 +1787,7 @@ HTREEITEM AddToTreeEx (HWND hwndTree, LPWSTR lpszId; GUID guidClass; BOOL fEnabled; - ULONG ulStatus; + ULONG ulStatus{}; HTREEITEM hTreeItem; TV_INSERTSTRUCTW tvInsertStruc; HRESULT hr; diff --git a/network/config/bindview/BINDVIEW.H b/network/config/bindview/BINDVIEW.H index 2753b753..1a1d4a80 100644 --- a/network/config/bindview/BINDVIEW.H +++ b/network/config/bindview/BINDVIEW.H @@ -7,7 +7,7 @@ // // Contents: Function Prototypes // -// Notes: +// Notes: // // Author: Alok Sinha 15-May-01 // diff --git a/network/config/bindview/NetCfgAPI.cpp b/network/config/bindview/NetCfgAPI.cpp index 5080bb41..bdbb8e52 100644 --- a/network/config/bindview/NetCfgAPI.cpp +++ b/network/config/bindview/NetCfgAPI.cpp @@ -248,7 +248,7 @@ HRESULT HrInstallNetComponent (IN INetCfg *pnc, { hr = E_OUTOFMEMORY; break; - } + } ZeroMemory(DirWithDrive, (_MAX_DRIVE + _MAX_DIR) * sizeof(WCHAR)); // @@ -329,7 +329,7 @@ HRESULT HrInstallNetComponent (IN INetCfg *pnc, { CoTaskMemFree(DirWithDrive); DirWithDrive = NULL; - } + } return hr; } diff --git a/network/config/bindview/NetCfgAPI.h b/network/config/bindview/NetCfgAPI.h index b4d6f552..310b36b2 100644 --- a/network/config/bindview/NetCfgAPI.h +++ b/network/config/bindview/NetCfgAPI.h @@ -7,7 +7,7 @@ // // Contents: Functions Prototypes // -// Notes: +// Notes: // // Author: Alok Sinha 15-May-01 // diff --git a/network/config/bindview/RESOURCE.H b/network/config/bindview/RESOURCE.H index 3fb76696..06cd3681 100644 --- a/network/config/bindview/RESOURCE.H +++ b/network/config/bindview/RESOURCE.H @@ -32,7 +32,7 @@ #define IDI_DISABLE 40007 // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 109 diff --git a/network/modem/fakemodem/driver.c b/network/modem/fakemodem/driver.c index 572e462f..1027fda7 100644 --- a/network/modem/fakemodem/driver.c +++ b/network/modem/fakemodem/driver.c @@ -15,8 +15,8 @@ Abstract: This is a simple form of function driver for fakemodem device. The driver doesn't handle any PnP and Power events because the framework provides - default behaviour for those events. This driver has enough support to - allow an user application (toast/notify.exe) to open the device + default behavior for those events. This driver has enough support to + allow a user application (toast/notify.exe) to open the device interface registered by the driver and send read, write or ioctl requests. Environment: @@ -232,7 +232,7 @@ Return Value: &defQueue // pointer to default queue ); __analysis_assume(queueConfig.EvtIoStop == 0); - + if (!NT_SUCCESS (status)) { // @@ -256,7 +256,7 @@ Return Value: &fmDeviceData->FmReadQueue ); __analysis_assume(queueConfig.EvtIoStop == 0); - + if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; @@ -276,7 +276,7 @@ Return Value: &fmDeviceData->FmMaskWaitQueue ); __analysis_assume(queueConfig.EvtIoStop == 0); - + if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; diff --git a/network/modem/fakemodem/ioctl.c b/network/modem/fakemodem/ioctl.c index 445910bd..a3268cd2 100644 --- a/network/modem/fakemodem/ioctl.c +++ b/network/modem/fakemodem/ioctl.c @@ -689,7 +689,7 @@ Return Value: case IOCTL_SERIAL_SET_HANDFLOW: case IOCTL_SERIAL_RESET_DEVICE: { // - // NOTE: The application expects STATUS_SUCCESS for these ioctsl. + // NOTE: The application expects STATUS_SUCCESS for these ioctls. // so don't merge this with default. // break; diff --git a/network/modem/fakemodem/readwrit.c b/network/modem/fakemodem/readwrit.c index af6da937..fbce3e9a 100644 --- a/network/modem/fakemodem/readwrit.c +++ b/network/modem/fakemodem/readwrit.c @@ -9,14 +9,14 @@ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: - ioctl.c + readwrit.c Abstract: This is a simple form of function driver for Fm device. The driver doesn't handle any PnP and Power events because the framework provides - default behaviour for those events. This driver has enough support to - allow an user application (toast/notify.exe) to open the device + default behavior for those events. This driver has enough support to + allow a user application (toast/notify.exe) to open the device interface registered by the driver and send read, write or ioctl requests. Environment: @@ -49,8 +49,8 @@ Arguments: Length - Length of the IO operation The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get + zero length read & write requests to the driver and + complete it with status success. So we will never get a zero length request. Return Value: @@ -117,8 +117,8 @@ Arguments: Length - Length of the IO operation The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get + zero length read & write requests to the driver and + complete it with status success. So we will never get a zero length request. Return Value: @@ -193,8 +193,8 @@ Arguments: Length - Length of the IO operation The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get + zero length read & write requests to the driver and + complete it with status success. So we will never get a zero length request. Return Value: diff --git a/network/ndis/extension/base/SxApi.h b/network/ndis/extension/base/SxApi.h index 64dca5f7..a8c4c0db 100644 --- a/network/ndis/extension/base/SxApi.h +++ b/network/ndis/extension/base/SxApi.h @@ -47,7 +47,7 @@ extern PWCHAR SxExtServiceName; extern ULONG SxExtAllocationTag; // -// The request ID used to identify OIDs initiated from this extension. +// The request ID used to identify OIDs initiated from this extension. // extern ULONG SxExtOidRequestId; @@ -55,19 +55,19 @@ extern ULONG SxExtOidRequestId; /*++ SxExtInitialize - + Routine Description: This function is called from the SxBase Library during DriverEntry. - An extension should allocate/initalize all global data in this function. - + An extension should allocate/initialize all global data in this function. + Arguments: NULL - + Return Value: NDIS_STATUS_SUCCESS succeeds driver entry. - + NDIS_STATUS_*** fails driver entry. - + --*/ NDIS_STATUS SxExtInitialize(); @@ -76,17 +76,17 @@ SxExtInitialize(); /*++ SxExtUninitialize - + Routine Description: This function is called from the SxBase Library during DriverUnload. An extension should free/reset all global data in this function. - + Arguments: NULL - + Return Value: VOID - + --*/ VOID SxExtUninitialize(); @@ -95,28 +95,28 @@ SxExtUninitialize(); /*++ SxExtCreateSwitch - + Routine Description: This function is called when an extension binds to a new switch. All switch specific data should be allocated during this function. OIDs cannot be sent from this function, and both the control and data paths are inactive. - + Arguments: Switch - the Switch Object currently being created - + ExtensionContext - Extension context specific to the switch being createf. This context will be passed back to the extension for all function calls in SxApi - + Return Value: NDIS_STATUS_SUCCESS succeeds switch creation. - + NDIS_STATUS_RESOURCES fails switch creation because of insufficient resources. - + NDIS_STATUS_FAILURE fails switch creation. - + --*/ NDIS_STATUS SxExtCreateSwitch( @@ -124,25 +124,25 @@ SxExtCreateSwitch( _Outptr_result_maybenull_ PNDIS_HANDLE *ExtensionContext ); - + /*++ SxExtDeleteSwitch - + Routine Description: This function is called when an extension binds to a new switch. All switch specific data should be allocated/initialized during this function. - + Arguments: Switch - the Switch being deleted - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch being deleted. - + Return Value: VOID - + --*/ VOID SxExtDeleteSwitch( @@ -150,54 +150,54 @@ SxExtDeleteSwitch( _In_ NDIS_HANDLE ExtensionContext ); - + /*++ SxExtActivateSwitch - + Routine Description: This function is called to activate a switch. The function can be called while the switch is Running or Paused and should be used to bootstrap the switch if it was not Active when it was created. - + Arguments: Switch - the Switch being activated - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch being restarted. - + Return Value: VOID - ---*/ + +--*/ VOID SxExtActivateSwitch( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext ); - + /*++ SxExtRestartSwitch - + Routine Description: This function is called to restart a switch from a paused state. - + Arguments: Switch - the Switch being restarted - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch being restarted. - + Return Value: NDIS_STATUS_SUCCESS succeeds switch restart. - + NDIS_STATUS_RESOURCES fails switch restart because of insufficient resources. - + NDIS_STATUS_FAILURE fails switch restart. - + --*/ NDIS_STATUS SxExtRestartSwitch( @@ -209,20 +209,20 @@ SxExtRestartSwitch( /*++ SxExtPauseSwitch - + Routine Description: This function is called to pause a switch from a running state. - + Arguments: Switch - the Switch being paused - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch being paused - + Return Value: VOID - ---*/ + +--*/ VOID SxExtPauseSwitch( _In_ PSX_SWITCH_OBJECT Switch, @@ -233,24 +233,24 @@ SxExtPauseSwitch( /*++ SxExtCreatePort - + Routine Description: This function is called to create a new port on a switch. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Port - the Port being created - + Return Value: NDIS_STATUS_SUCCESS to succeed port creation - + NDIS_STATUS_*** to fail port creation - ---*/ + +--*/ NDIS_STATUS SxExtCreatePort( _In_ PSX_SWITCH_OBJECT Switch, @@ -258,26 +258,26 @@ SxExtCreatePort( _In_ PNDIS_SWITCH_PORT_PARAMETERS Port ); - + /*++ SxExtUpdatePort - + Routine Description: This function is called to update an already created port. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Port - the port being updated - + Return Value: VOID - ---*/ + +--*/ VOID SxExtUpdatePort( _In_ PSX_SWITCH_OBJECT Switch, @@ -285,32 +285,32 @@ SxExtUpdatePort( _In_ PNDIS_SWITCH_PORT_PARAMETERS Port ); - + /*++ SxExtCreateNic - + Routine Description: This function is called to create a new NIC to be connected to a switch. The extension may allocate context for this NIC, and traffic may start to flow from this NIC, but it may not be used as a destination until SxExtConnectNic has been called. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Nic - the NIC being created - + Return Value: NDIS_STATUS_SUCCESS to succeed NIC creation - + NDIS_STATUS_*** to fail NIC creation - ---*/ + +--*/ NDIS_STATUS SxExtCreateNic( _In_ PSX_SWITCH_OBJECT Switch, @@ -318,28 +318,28 @@ SxExtCreateNic( _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic ); - + /*++ SxExtConnectNic - + Routine Description: This function is called to connect a NIC to a switch. After returning from this function the extension can use this NIC as a destination. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Nic - the NIC being connected - + Return Value: VOID - ---*/ + +--*/ VOID SxExtConnectNic( _In_ PSX_SWITCH_OBJECT Switch, @@ -347,26 +347,26 @@ SxExtConnectNic( _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic ); - + /*++ SxExtUpdateNic - + Routine Description: This function is called to update an already created NIC. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Nic - the NIC being updated - + Return Value: VOID - ---*/ + +--*/ VOID SxExtUpdateNic( _In_ PSX_SWITCH_OBJECT Switch, @@ -374,28 +374,28 @@ SxExtUpdateNic( _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic ); - + /*++ SxExtDisconnectNic - + Routine Description: This function is called to disconnect a NIC from a switch. After returning from this function the extension cannot use this NIC as a destination. - + Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Nic - the NIC being disconnected - + Return Value: VOID - ---*/ + +--*/ VOID SxExtDisconnectNic( _In_ PSX_SWITCH_OBJECT Switch, @@ -403,26 +403,26 @@ SxExtDisconnectNic( _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic ); - + /*++ SxExtDeleteNic - + Routine Description: This function is called to delete a NIC from a switch. - No futher traffic/control will be recieved for this NIC. + No further traffic/control will be received for this NIC. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Nic - the NIC being deleted - + Return Value: VOID - + --*/ VOID SxExtDeleteNic( @@ -431,27 +431,27 @@ SxExtDeleteNic( _In_ PNDIS_SWITCH_NIC_PARAMETERS Nic ); - + /*++ SxExtTeardownPort - + Routine Description: This function is called to start deletion of a port on a switch. - Upon recieving this call, no further references may be taken + Upon receiving this call, no further references may be taken on the given port. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Port - the Port being deleted - + Return Value: VOID - + --*/ VOID SxExtTeardownPort( @@ -464,78 +464,78 @@ SxExtTeardownPort( /*++ SxExtDeletePort - + Routine Description: This function is called to finish deletion of a port on a switch. - Upon recieving this call, no traffic/control will be recieved + Upon receiving this call, no traffic/control will be received for this port. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + Port - the Port being deleted - + Return Value: VOID - + --*/ VOID -SxExtDeletePort( +SxExtDeletePort( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext, _In_ PNDIS_SWITCH_PORT_PARAMETERS Port ); - + /*++ SxExtSaveNic - + Routine Description: This function is called to retrieve save data for a given NIC. This function will be called until all extensions have finished saving data. - + An new save for this NIC will not start until SxExtSaveNicComplete has been received. - + If returning NDIS_STATUS_SUCCESS from this function, and BytesWritten > 0 you must write to the ExtensionId, ExtensionFriendlyName, SaveDataSize and SaveData fields in SaveState. SxExtUniqueName MUST be written to ExtensionId. SxExtFriendlyName should be written to ExtensionFriendlyName. - + If returning NDIS_STATUS_SUCCESS with BytesWritten == 0, DO NOT write any data to any fields. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SaveState - the save information and buffer to save to - + BytesWritten - the # of bytes written to the save buffer - + BytesNeeded - the length of the save buffer needed - + Return Value: NDIS_STATUS_SUCCESS - if the buffer was successfully written, or not needed and BytesWritten is set to 0 - + NDIS_STATUS_BUFFER_TOO_SHORT - if the buffer is too short for the necessary save, write the length needed in BytesNeeded NDIS_STATUS_*** - to fail the save operation - + --*/ NDIS_STATUS -SxExtSaveNic( +SxExtSaveNic( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext, _Inout_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState, @@ -547,123 +547,123 @@ SxExtSaveNic( /*++ SxExtSaveNicComplete - + Routine Description: This function is called to notify the extension that saving the given NIC has been completed by all extensions. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SaveState - the save information - + Return Value: VOID - ---*/ + +--*/ VOID -SxExtSaveNicComplete( +SxExtSaveNicComplete( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext, _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState ); - + /*++ SxExtNicRestore - + Routine Description: This function is called to restore previously saved data. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SaveState - the save information - + BytesRestored - the number of bytes restored from the saved data - + Return Value: NDIS_STATUS_SUCCESS - if this data belongs to this extension, and was successfully restored (BytesRestored written) OR this data does not belong to this extension - (BytesRestored == 0) - + (BytesRestored == 0) + NDIS_STATUS_*** - there was an error while attempting to restore this data - ---*/ + +--*/ NDIS_STATUS -SxExtNicRestore( +SxExtNicRestore( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext, _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState, _Out_ PULONG BytesRestored ); - + /*++ SxExtNicRestoreComplete - + Routine Description: This function is called to signify the end of a restore operation. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SaveState - the save information - + Return Value: VOID - ---*/ + +--*/ VOID -SxExtNicRestoreComplete( +SxExtNicRestoreComplete( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_HANDLE ExtensionContext, _In_ PNDIS_SWITCH_NIC_SAVE_STATE SaveState ); - - + + /*++ SxExtAddSwitchProperty - + Routine Description: This function is called to add a property on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SwitchProperty - the property to be applied - + Return Value: NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension - + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and can successfully be enforced - + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this extension, but cannot be enforced - + NDIS_STATUS_*** - if the policy is consumed by this extension, and setting the valid policy failed - ---*/ + +--*/ NDIS_STATUS SxExtAddSwitchProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -675,31 +675,31 @@ SxExtAddSwitchProperty( /*++ SxExtUpdateSwitchProperty - + Routine Description: This function is called to update a property on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SwitchProperty - the property to be updated - + Return Value: NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension - + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and can successfully be enforced - + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this extension, but cannot be enforced - + NDIS_STATUS_*** - if the policy is consumed by this extension, and setting the valid policy failed - ---*/ + +--*/ NDIS_STATUS SxExtUpdateSwitchProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -707,28 +707,28 @@ SxExtUpdateSwitchProperty( _In_ PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty ); - + /*++ SxExtDeleteSwitchProperty - + Routine Description: This function is called to delete a property on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SwitchProperty - the property to be deleted - + Return Value: TRUE - if the policy belongs to this extension - + FALSE - otherwise - ---*/ + +--*/ BOOLEAN SxExtDeleteSwitchProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -740,32 +740,32 @@ SxExtDeleteSwitchProperty( /*++ SxExtAddPortProperty - + Routine Description: This function is called to add a property on the given port, on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + PortProperty - the property to be applied - + Return Value: NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension - + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and can successfully be enforced - + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this extension, but cannot be enforced - + NDIS_STATUS_*** - if the policy is consumed by this extension, and setting the valid policy failed - ---*/ + +--*/ NDIS_STATUS SxExtAddPortProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -777,32 +777,32 @@ SxExtAddPortProperty( /*++ SxExtUpdatePortProperty - + Routine Description: This function is called to update a property on the given port, on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + PortProperty - the property to be applied - + Return Value: NDIS_STATUS_NOT_SUPPORTED - if the policy is not consumed by this extension - + NDIS_STATUS_SUCCESS - if the policy is consumed by this extension, and can successfully be enforced - + STATUS_DATA_NOT_ACCEPTED - if the policy is consumed by this extension, but cannot be enforced - + NDIS_STATUS_*** - if the policy is consumed by this extension, and setting the valid policy failed - ---*/ + +--*/ NDIS_STATUS SxExtUpdatePortProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -810,29 +810,29 @@ SxExtUpdatePortProperty( _In_ PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty ); - + /*++ SxExtDeletePortProperty - + Routine Description: This function is called to delete a property on the given port, on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - - SwitchProperty - the property to be deleted - + + PortProperty - the property to be deleted + Return Value: TRUE - if the policy is not consumed by this extension - + FALSE - otherwise - ---*/ + +--*/ BOOLEAN SxExtDeletePortProperty( _In_ PSX_SWITCH_OBJECT Switch, @@ -840,33 +840,33 @@ SxExtDeletePortProperty( _In_ PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS PortProperty ); - + /*++ SxExtQuerySwitchFeatureStatus - + Routine Description: This function is called to query the status of a custom property on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + SwitchFeatureStatus - the property buffer - + BytesNeeded - if SwitchFeatureStatus is too small, this should be set to the size buffer needed - + Return Value: TRUE - return true if this property belongs to this extension, if BytesNeeded > 0, the buffer will be reallocated and this function will be called again - + FALSE - otherwise - + --*/ BOOLEAN SxExtQuerySwitchFeatureStatus( @@ -880,29 +880,29 @@ SxExtQuerySwitchFeatureStatus( /*++ SxExtQueryPortFeatureStatus - + Routine Description: This function is called to query the status of a custom property on the given port, on the given switch. Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + PortFeatureStatus - the property buffer - + BytesNeeded - if PortFeatureStatus is too small, this should be set to the size buffer needed - + Return Value: TRUE - return true if this property belongs to this extension, if BytesNeeded > 0, the buffer will be reallocated and this function will be called again - + FALSE - otherwise - + --*/ BOOLEAN SxExtQueryPortFeatureStatus( @@ -911,14 +911,14 @@ SxExtQueryPortFeatureStatus( _Inout_ PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS PortFeatureStatus, _Inout_ PULONG BytesNeeded ); - - + + /*++ SxExtProcessNicRequest - + Routine Description: - This function is called upon the reciept of an OID_SWITCH_NIC_REQUEST + This function is called upon the receipt of an OID_SWITCH_NIC_REQUEST to the extension. If an extension wishes to redirect the OID, it must return a valid DestinationPortId and DestinationNicIndex, which it has taken a @@ -927,30 +927,30 @@ Routine Description: a valid SourcePortId and SourceNicIndex, which it has taken a reference on. The extension can change the OidRequest if it needs to. - + !! This function should only be used by forwarding extensions. !! Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + OidRequest - the OID wrapped by the NIC request - + SourcePortId - the source PortId to set - + SourceNicIndex - the source NicIndex to set - + DestinationPortId - the destination PortId to set - + DestinationNicIndex - the destination NicIndex to set - + Return Value: NDIS_STATUS_SUCCESS - sends OID - + NDIS_STATUS_*** - complete OID with given status - + --*/ NDIS_STATUS SxExtProcessNicRequest( @@ -967,7 +967,7 @@ SxExtProcessNicRequest( /*++ SxExtProcessNicRequestComplete - + Routine Description: This function is called upon the completion of an OID_SWITCH_NIC_REQUEST that this extension has previously altered. @@ -978,18 +978,26 @@ Routine Description: Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - - NicOidRequest - the OID buffer, encapsulated with source/destination info - + + OidRequest - the OID buffer, encapsulated with source/destination info + + SourcePortId - the source PortId of the OID completion + + SourceNicIndex - the source NicIndex of the OID completion + + DestinationPortId - the destination PortId of the OID completion + + DestinationNicIndex - the destination NicIndex of the OID completion + Status - the status the OID completed with - + Return Value: NDIS_STATUS - the status to complete the OID request with - ---*/ + +--*/ NDIS_STATUS SxExtProcessNicRequestComplete( _In_ PSX_SWITCH_OBJECT Switch, @@ -1001,43 +1009,43 @@ SxExtProcessNicRequestComplete( _In_ NDIS_SWITCH_NIC_INDEX DestinationNicIndex, _In_ NDIS_STATUS Status ); - + /*++ SxExtProcessNicStatus - + Routine Description: - This function is called upon the reciept of an NDIS_STATUS_SWITCH_NIC_STATUS + This function is called upon the receipt of an NDIS_STATUS_SWITCH_NIC_STATUS to the extension. If the extension wishes to modify the status indication, it should send its own status indication using NdisFIndicateStatus and return a failure status. - If the extension wishes to drop the status indiction, it should return + If the extension wishes to drop the status indication, it should return failure status, though this should be done very sparingly and carefully. - + !! This function should only be used by forwarding extensions. !! Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + StatusIndication - the indication wrapped by the NIC status indication - + SourcePortId - the source PortId of the indication - + SourceNicIndex - the source NicIndex of the indication - + Return Value: NDIS_STATUS_SUCCESS - return to continue forwarding this indication - + NDIS_STATUS_*** - if the extension wants to modify the status if modifying the status the extension should indicate its own modified status using SxLibIssueNicStatusIndicationUnsafe as soon as possible - + --*/ NDIS_STATUS SxExtProcessNicStatus( @@ -1048,11 +1056,11 @@ SxExtProcessNicStatus( _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex ); - + /*++ SxExtStartNetBufferListsIngress - + Routine Description: This function is called upon the receipt on an NBL on ingress. The extension should call SxLibSendNetBufferListsIngress to continue @@ -1063,19 +1071,19 @@ Routine Description: Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + NetBufferLists - the NBL to be sent - + SendFlags - the send flags from NDIS, equivalent to NDIS send flags for NdisFSendNetBufferLists - + Return Value: VOID - ---*/ + +--*/ VOID SxExtStartNetBufferListsIngress( _In_ PSX_SWITCH_OBJECT Switch, @@ -1088,7 +1096,7 @@ SxExtStartNetBufferListsIngress( /*++ SxExtStartNetBufferListsEgress - + Routine Description: This function is called upon the receipt on an NBL on egress. The extension should call SxLibSendNetBufferListsEgress to continue @@ -1098,21 +1106,21 @@ Routine Description: Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + NetBufferLists - the NBL to be sent - + NumberOfNetBufferLists - the number of NBLs in NetBufferLists - + ReceiveFlags - the receive flags from NDIS, equivalent to NDIS receive flags for NdisFIndicateReceiveNetBufferLists - + Return Value: VOID - ---*/ + +--*/ VOID SxExtStartNetBufferListsEgress( _In_ PSX_SWITCH_OBJECT Switch, @@ -1122,11 +1130,11 @@ SxExtStartNetBufferListsEgress( _In_ ULONG ReceiveFlags ); - + /*++ SxExtStartCompleteNetBufferListsEgress - + Routine Description: This function is called upon the completion of an NBL on egress. The extension must call SxLibCompleteNetBufferListsEgress @@ -1134,19 +1142,19 @@ Routine Description: Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + NetBufferLists - the NBL being completed - + ReturnFlags - the return flags from NDIS, equivalent to NDIS return flags for NdisFReturnNetBufferLists - + Return Value: VOID - ---*/ + +--*/ VOID SxExtStartCompleteNetBufferListsEgress( _In_ PSX_SWITCH_OBJECT Switch, @@ -1155,16 +1163,16 @@ SxExtStartCompleteNetBufferListsEgress( _In_ ULONG ReturnFlags ); - + /*++ SxExtStartCompleteNetBufferListsIngress - + Routine Description: This function is called upon the completion of an NBL on ingress. The extension must call SxLibCompleteNetBufferListsIngress once it has finished processing the NBL. - + If there are NBLs injected by this extension in NetBufferLists, the extension must NOT call SxLibCompleteNetBufferListsIngress, and instead call SxLibCompletedInjectedNetBufferLists with the number @@ -1172,20 +1180,20 @@ Routine Description: Arguments: Switch - the Switch context - + ExtensionContext - The extension context allocated in SxExtCreateSwitch for the switch - + NetBufferLists - the NBL being completed - + SendCompleteFlags - the send complete flags from NDIS, equivalent to NDIS send complete flags for NdisFSendNetBufferListsComplete - + Return Value: VOID - ---*/ + +--*/ VOID SxExtStartCompleteNetBufferListsIngress( _In_ PSX_SWITCH_OBJECT Switch, @@ -1193,4 +1201,4 @@ SxExtStartCompleteNetBufferListsIngress( _In_ PNET_BUFFER_LIST NetBufferLists, _In_ ULONG SendCompleteFlags ); - + diff --git a/network/ndis/extension/base/SxBase.c b/network/ndis/extension/base/SxBase.c index f45f8b79..ad84138a 100644 --- a/network/ndis/extension/base/SxBase.c +++ b/network/ndis/extension/base/SxBase.c @@ -42,7 +42,7 @@ SxpNdisProcessMethodOid( _Out_ PULONG BytesNeeded ); - + // // DriverEntry // http://msdn.microsoft.com/en-us/library/ff544113(v=VS.85).aspx @@ -59,7 +59,7 @@ DriverEntry( NDIS_STRING serviceName; UNREFERENCED_PARAMETER(RegistryPath); - + // // Initialize extension specific data. // @@ -86,10 +86,10 @@ DriverEntry( fChars.FriendlyName = SxExtensionFriendlyName; fChars.UniqueName = SxExtensionGuid; fChars.ServiceName = serviceName; - + fChars.SetOptionsHandler = SxNdisSetOptions; fChars.SetFilterModuleOptionsHandler = SxNdisSetFilterModuleOptions; - + fChars.AttachHandler = SxNdisAttach; fChars.DetachHandler = SxNdisDetach; fChars.PauseHandler = SxNdisPause; @@ -100,14 +100,14 @@ DriverEntry( fChars.CancelSendNetBufferListsHandler = SxNdisCancelSendNetBufferLists; fChars.ReceiveNetBufferListsHandler = SxNdisReceiveNetBufferLists; fChars.ReturnNetBufferListsHandler = SxNdisReturnNetBufferLists; - + fChars.OidRequestHandler = SxNdisOidRequest; fChars.OidRequestCompleteHandler = SxNdisOidRequestComplete; fChars.CancelOidRequestHandler = SxNdisCancelOidRequest; - + fChars.NetPnPEventHandler = SxNdisNetPnPEvent; fChars.StatusHandler = SxNdisStatus; - + NdisAllocateSpinLock(&SxExtensionListLock); InitializeListHead(&SxExtensionList); @@ -129,7 +129,7 @@ Cleanup: } NdisFreeSpinLock(&SxExtensionListLock); - + SxExtUninitialize(); } @@ -150,7 +150,7 @@ SxNdisUnload( UNREFERENCED_PARAMETER(DriverObject); SxExtUninitialize(); - + NdisFDeregisterFilterDriver(SxDriverHandle); NdisFreeSpinLock(&SxExtensionListLock); } @@ -171,7 +171,7 @@ SxNdisSetOptions( UNREFERENCED_PARAMETER(DriverContext); return NDIS_STATUS_SUCCESS; } - + // // FilterSetModuleOptions Function @@ -206,7 +206,7 @@ SxNdisAttach( NDIS_SWITCH_CONTEXT switchContext; NDIS_SWITCH_OPTIONAL_HANDLERS switchHandler; PSX_SWITCH_OBJECT switchObject; - + UNREFERENCED_PARAMETER(SxDriverContext); DEBUGP(DL_TRACE, ("===>SxAttach: NdisFilterHandle %p\n", NdisFilterHandle)); @@ -291,11 +291,11 @@ SxNdisAttach( switchObject->ControlFlowState = SxSwitchAttached; switchObject->DataFlowState = SxSwitchPaused; - + NdisAcquireSpinLock(&SxExtensionListLock); InsertHeadList(&SxExtensionList, &switchObject->Link); NdisReleaseSpinLock(&SxExtensionListLock); - + Cleanup: if (status != NDIS_STATUS_SUCCESS) @@ -331,24 +331,24 @@ SxNdisDetach( // NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused); switchObject->ControlFlowState = SxSwitchDetached; - + KeMemoryBarrier(); - + while(switchObject->PendingOidCount > 0) { NdisMSleep(1000); } - + SxExtDeleteSwitch(switchObject, switchObject->ExtensionContext); NdisAcquireSpinLock(&SxExtensionListLock); RemoveEntryList(&switchObject->Link); NdisReleaseSpinLock(&SxExtensionListLock); - + ExFreePool(switchObject); // - // Alway return success. + // Always return success. // DEBUGP(DL_TRACE, ("<===SxDetach Successfully\n")); @@ -375,15 +375,15 @@ SxNdisPause( ("===>NDISLWF SxPause: SxInstance %p\n", FilterModuleContext)); SxExtPauseSwitch(switchObject, switchObject->ExtensionContext); - + // // Set the flag that the filter is going to pause. // NT_ASSERT(switchObject->DataFlowState == SxSwitchRunning); switchObject->DataFlowState = SxSwitchPaused; - + KeMemoryBarrier(); - + while(switchObject->PendingInjectedNblCount > 0) { NdisMSleep(1000); @@ -413,7 +413,7 @@ SxNdisRestart( DEBUGP(DL_TRACE, ("===>SxRestart: FilterModuleContext %p\n", FilterModuleContext)); - + status = SxExtRestartSwitch(switchObject, switchObject->ExtensionContext); if (status != NDIS_STATUS_SUCCESS) @@ -424,7 +424,7 @@ SxNdisRestart( NT_ASSERT(switchObject->DataFlowState == SxSwitchPaused); switchObject->DataFlowState = SxSwitchRunning; - + DEBUGP(DL_TRACE, ("<===SxRestart: FilterModuleContext %p, status %x\n", FilterModuleContext, @@ -452,11 +452,11 @@ SxNdisOidRequest( PVOID *cloneRequestContext; BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; - + status = NDIS_STATUS_SUCCESS; DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest)); - + NdisInterlockedIncrement(&switchObject->PendingOidCount); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, @@ -471,15 +471,15 @@ SxNdisOidRequest( cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]); *cloneRequestContext = OidRequest; - + switch (clonedRequest->RequestType) - { + { case NdisRequestSetInformation: status = SxpNdisProcessSetOid(switchObject, clonedRequest, &completeOid); break; - + case NdisRequestMethod: status = SxpNdisProcessMethodOid(switchObject, clonedRequest, @@ -488,7 +488,7 @@ SxNdisOidRequest( break; } - + if (completeOid) { NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest); @@ -580,7 +580,7 @@ SxNdisOidRequestComplete( NdisOidRequest->DATA.METHOD_INFORMATION.BytesNeeded; originalRequest->DATA.METHOD_INFORMATION.BytesWritten = NdisOidRequest->DATA.METHOD_INFORMATION.BytesWritten; - + if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_NIC_REQUEST && switchObject->OldNicRequest != NULL) { @@ -593,23 +593,23 @@ SxNdisOidRequestComplete( nicOidRequestBuf->DestinationPortId, nicOidRequestBuf->DestinationNicIndex, Status); - + originalRequest->DATA.METHOD_INFORMATION.InformationBuffer = switchObject->OldNicRequest; switchObject->OldNicRequest = NULL; ExFreePoolWithTag(nicOidRequestBuf, SxExtAllocationTag); } - + break; case NdisRequestSetInformation: header = originalRequest->DATA.SET_INFORMATION.InformationBuffer; - + originalRequest->DATA.SET_INFORMATION.BytesRead = NdisOidRequest->DATA.SET_INFORMATION.BytesRead; originalRequest->DATA.SET_INFORMATION.BytesNeeded = NdisOidRequest->DATA.SET_INFORMATION.BytesNeeded; - + if (NdisOidRequest->DATA.METHOD_INFORMATION.Oid == OID_SWITCH_PORT_CREATE && Status != NDIS_STATUS_SUCCESS) { @@ -623,7 +623,7 @@ SxNdisOidRequestComplete( SxExtDeleteNic(switchObject, switchObject->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); - + } break; @@ -647,7 +647,7 @@ SxNdisOidRequestComplete( Status); DEBUGP(DL_TRACE, ("<===SxOidRequestComplete.\n")); - + Cleanup: NdisInterlockedDecrement(&switchObject->PendingOidCount); } @@ -667,7 +667,7 @@ SxNdisSendNetBufferLists( ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; - + UNREFERENCED_PARAMETER(PortNumber); SxExtStartNetBufferListsIngress(switchObject, @@ -713,7 +713,7 @@ SxNdisReceiveNetBufferLists( ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; - + UNREFERENCED_PARAMETER(PortNumber); SxExtStartNetBufferListsEgress(switchObject, @@ -773,9 +773,9 @@ SxNdisNetPnPEvent( ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; - + if (NetPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) - { + { // // Switch Activation must be passed along regardless of successful // initialization. @@ -783,7 +783,7 @@ SxNdisNetPnPEvent( SxExtActivateSwitch(switchObject, switchObject->ExtensionContext); } - + return NdisFNetPnPEvent(switchObject->NdisFilterHandle, NetPnPEvent); } @@ -804,14 +804,14 @@ SxNdisStatus( PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; PNDIS_SWITCH_NIC_STATUS_INDICATION nicIndication; PNDIS_STATUS_INDICATION originalIndication; - + if (StatusIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION || StatusIndication->Header.Revision != NDIS_STATUS_INDICATION_REVISION_1 || StatusIndication->Header.Size < NDIS_SIZEOF_STATUS_INDICATION_REVISION_1) { goto Cleanup; } - + // // Only NDIS_STATUS_SWITCH_NIC_STAUTUS indications need to be processed // by switch extensions. @@ -820,24 +820,24 @@ SxNdisStatus( { goto Cleanup; } - + nicIndication = StatusIndication->StatusBuffer; - + if (nicIndication->Header.Type != NDIS_OBJECT_TYPE_STATUS_INDICATION || nicIndication->Header.Revision != NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1 || nicIndication->Header.Size < NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1) { goto Cleanup; } - + originalIndication = nicIndication->StatusIndication; - + status = SxExtProcessNicStatus(switchObject, switchObject->ExtensionContext, originalIndication, nicIndication->SourcePortId, nicIndication->SourceNicIndex); - + Cleanup: if (status == NDIS_STATUS_SUCCESS) { @@ -846,7 +846,7 @@ Cleanup: } return; - + } @@ -861,26 +861,26 @@ SxpNdisProcessSetOid( NDIS_OID oid = OidRequest->DATA.SET_INFORMATION.Oid; PNDIS_OBJECT_HEADER header; ULONG bytesRestored = 0; - + *Complete = FALSE; - + header = OidRequest->DATA.SET_INFORMATION.InformationBuffer; - + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != 0 && - OidRequest->DATA.SET_INFORMATION.InformationBufferLength < + OidRequest->DATA.SET_INFORMATION.InformationBufferLength < sizeof(NDIS_OBJECT_HEADER)) { status = NDIS_STATUS_NOT_SUPPORTED; *Complete = TRUE; goto Cleanup; } - + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength == 0) { *Complete = FALSE; goto Cleanup; } - + switch(oid) { case OID_SWITCH_PROPERTY_ADD: @@ -893,7 +893,7 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + if (oid == OID_SWITCH_PROPERTY_ADD) { status = SxExtAddSwitchProperty(Switch, @@ -906,7 +906,7 @@ SxpNdisProcessSetOid( Switch->ExtensionContext, (PNDIS_SWITCH_PROPERTY_PARAMETERS)header); } - + if (status == NDIS_STATUS_NOT_SUPPORTED) { status = NDIS_STATUS_SUCCESS; @@ -916,7 +916,7 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + break; case OID_SWITCH_PROPERTY_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || @@ -927,13 +927,13 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + *Complete = SxExtDeleteSwitchProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS)header); - + break; - + case OID_SWITCH_PORT_PROPERTY_ADD: case OID_SWITCH_PORT_PROPERTY_UPDATE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || @@ -944,7 +944,7 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + if (oid == OID_SWITCH_PORT_PROPERTY_ADD) { status = SxExtAddPortProperty(Switch, @@ -957,7 +957,7 @@ SxpNdisProcessSetOid( Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS)header); } - + if (status == NDIS_STATUS_NOT_SUPPORTED) { status = NDIS_STATUS_SUCCESS; @@ -967,9 +967,9 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + break; - + case OID_SWITCH_PORT_PROPERTY_DELETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1 || @@ -979,13 +979,13 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + *Complete = SxExtDeletePortProperty(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS)header); - + break; - + case OID_SWITCH_PORT_CREATE: case OID_SWITCH_PORT_UPDATED: case OID_SWITCH_PORT_TEARDOWN: @@ -998,26 +998,26 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + if (oid == OID_SWITCH_PORT_CREATE) { status = SxExtCreatePort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); - + if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; } } else if (oid == OID_SWITCH_PORT_UPDATED) - { + { SxExtUpdatePort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } else if (oid == OID_SWITCH_PORT_TEARDOWN) - { + { SxExtTeardownPort(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); @@ -1028,9 +1028,9 @@ SxpNdisProcessSetOid( Switch->ExtensionContext, (PNDIS_SWITCH_PORT_PARAMETERS)header); } - + break; - + case OID_SWITCH_NIC_CREATE: case OID_SWITCH_NIC_CONNECT: case OID_SWITCH_NIC_UPDATED: @@ -1044,7 +1044,7 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + if (oid == OID_SWITCH_NIC_CREATE) { status = SxExtCreateNic(Switch, @@ -1056,7 +1056,7 @@ SxpNdisProcessSetOid( } } else if (oid == OID_SWITCH_NIC_CONNECT) - { + { SxExtConnectNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); @@ -1079,9 +1079,9 @@ SxpNdisProcessSetOid( Switch->ExtensionContext, (PNDIS_SWITCH_NIC_PARAMETERS)header); } - + break; - + case OID_SWITCH_NIC_RESTORE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || @@ -1090,12 +1090,12 @@ SxpNdisProcessSetOid( status = NDIS_STATUS_NOT_SUPPORTED; goto Cleanup; } - + status = SxExtNicRestore(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header, &bytesRestored); - + if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; @@ -1104,8 +1104,8 @@ SxpNdisProcessSetOid( { *Complete = TRUE; } - - break; + + break; case OID_SWITCH_NIC_SAVE_COMPLETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || @@ -1116,13 +1116,13 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + SxExtSaveNicComplete(Switch, Switch->ExtensionContext, - (PNDIS_SWITCH_NIC_SAVE_STATE)header); + (PNDIS_SWITCH_NIC_SAVE_STATE)header); break; - + case OID_SWITCH_NIC_RESTORE_COMPLETE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || @@ -1132,17 +1132,17 @@ SxpNdisProcessSetOid( *Complete = TRUE; goto Cleanup; } - + SxExtNicRestoreComplete(Switch, Switch->ExtensionContext, - (PNDIS_SWITCH_NIC_SAVE_STATE)header); + (PNDIS_SWITCH_NIC_SAVE_STATE)header); break; - + default: break; } - + Cleanup: return status; } @@ -1165,12 +1165,12 @@ SxpNdisProcessMethodOid( NDIS_SWITCH_NIC_INDEX destNic, sourceNic; ULONG bytesWritten = 0; ULONG bytesNeeded = 0; - + *Complete = FALSE; *BytesNeeded = 0; - + header = OidRequest->DATA.METHOD_INFORMATION.InformationBuffer; - + switch(oid) { case OID_SWITCH_FEATURE_STATUS_QUERY: @@ -1182,19 +1182,19 @@ SxpNdisProcessMethodOid( *Complete = TRUE; goto Cleanup; } - + *Complete = SxExtQuerySwitchFeatureStatus(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_FEATURE_STATUS_PARAMETERS)header, BytesNeeded); - + if (*BytesNeeded > 0) { status = NDIS_STATUS_BUFFER_TOO_SHORT; } - + break; - + case OID_SWITCH_PORT_FEATURE_STATUS_QUERY: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 || @@ -1204,19 +1204,19 @@ SxpNdisProcessMethodOid( *Complete = TRUE; goto Cleanup; } - + *Complete = SxExtQueryPortFeatureStatus(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_PORT_FEATURE_STATUS_PARAMETERS)header, BytesNeeded); - + if (*BytesNeeded > 0) { status = NDIS_STATUS_BUFFER_TOO_SHORT; } - + break; - + case OID_SWITCH_NIC_REQUEST: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1 || @@ -1226,14 +1226,14 @@ SxpNdisProcessMethodOid( *Complete = TRUE; goto Cleanup; } - + nicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)header; - + sourcePort = nicOidRequest->SourcePortId; sourceNic = nicOidRequest->SourceNicIndex; destPort = nicOidRequest->DestinationPortId; destNic = nicOidRequest->DestinationNicIndex; - + status = SxExtProcessNicRequest(Switch, Switch->ExtensionContext, nicOidRequest->OidRequest, @@ -1241,13 +1241,13 @@ SxpNdisProcessMethodOid( &sourceNic, &destPort, &destNic); - + if (status != NDIS_STATUS_SUCCESS) { *Complete = TRUE; goto Cleanup; } - + if (sourcePort != nicOidRequest->SourcePortId || sourceNic != nicOidRequest->SourceNicIndex || destPort != nicOidRequest->DestinationPortId || @@ -1255,31 +1255,31 @@ SxpNdisProcessMethodOid( { ASSERT(Switch->OldNicRequest == NULL); Switch->OldNicRequest = nicOidRequest; - + newNicOidRequest = (PNDIS_SWITCH_NIC_OID_REQUEST)ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof(NDIS_SWITCH_NIC_OID_REQUEST), SxExtAllocationTag); - + if (newNicOidRequest == NULL) { status = NDIS_STATUS_RESOURCES; *Complete = TRUE; goto Cleanup; } - + newNicOidRequest->Header = nicOidRequest->Header; newNicOidRequest->SourcePortId = sourcePort; newNicOidRequest->SourceNicIndex = sourceNic; newNicOidRequest->DestinationPortId = destPort; newNicOidRequest->DestinationNicIndex = destNic; newNicOidRequest->OidRequest = nicOidRequest->OidRequest; - + OidRequest->DATA.METHOD_INFORMATION.InformationBuffer = newNicOidRequest; } - + break; - + case OID_SWITCH_NIC_SAVE: if (header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < NDIS_SWITCH_NIC_SAVE_STATE_REVISION_1 || @@ -1289,13 +1289,13 @@ SxpNdisProcessMethodOid( *Complete = TRUE; goto Cleanup; } - + status = SxExtSaveNic(Switch, Switch->ExtensionContext, (PNDIS_SWITCH_NIC_SAVE_STATE)header, &bytesWritten, &bytesNeeded); - + if (status == NDIS_STATUS_SUCCESS && bytesWritten > 0) { @@ -1311,13 +1311,13 @@ SxpNdisProcessMethodOid( { *Complete = TRUE; } - + break; - + default: break; } - + Cleanup: return status; } @@ -1351,7 +1351,7 @@ Return Value: { PSX_OID_REQUEST oidRequest; ULONG bytesNeeded; - + UNREFERENCED_PARAMETER(Switch); bytesNeeded = 0; @@ -1381,7 +1381,7 @@ Return Value: // Save away the completion status. // oidRequest->Status = Status; - + // // Save bytesNeeded // diff --git a/network/ndis/extension/base/SxBase.h b/network/ndis/extension/base/SxBase.h index 5d34ee03..b5471f28 100644 --- a/network/ndis/extension/base/SxBase.h +++ b/network/ndis/extension/base/SxBase.h @@ -4,7 +4,7 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. Module Name: - SxBase.c + SxBase.h Abstract: @@ -58,18 +58,18 @@ typedef struct _SX_SWITCH_OBJECT // SX_SWITCH_DATAFLOW_STATE DataFlowState; SX_SWITCH_CONTROLFLOW_STATE ControlFlowState; - + // // Management fields. // volatile LONG PendingInjectedNblCount; volatile LONG PendingOidCount; - + // // Control Path Management. // PNDIS_SWITCH_NIC_OID_REQUEST OldNicRequest; - + } SX_SWITCH_OBJECT, *PSX_SWITCH_OBJECT; typedef struct _SX_OID_REQUEST diff --git a/network/ndis/extension/base/SxLibrary.c b/network/ndis/extension/base/SxLibrary.c index c4b12d45..196582f3 100644 --- a/network/ndis/extension/base/SxLibrary.c +++ b/network/ndis/extension/base/SxLibrary.c @@ -34,29 +34,29 @@ SxLibSendNetBufferListsIngress( PNET_BUFFER_LIST *curDropNbl = &dropNbl; NDIS_SWITCH_PORT_ID curSourcePort; NDIS_STRING filterReason; - + dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags); sameSource = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE); - + InterlockedAdd(&Switch->PendingInjectedNblCount, NumInjectedNetBufferLists); KeMemoryBarrier(); - + if (Switch->DataFlowState != SxSwitchRunning) { RtlInitUnicodeString(&filterReason, L"Extension Paused"); - + sendCompleteFlags = (dispatch) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0; sendCompleteFlags |= (sameSource) ? NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0; - + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); - + if (sameSource) { for (curNbl = NetBufferLists; curNbl != NULL; curNbl = curNbl->Next) { ++numNbls; } - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -66,11 +66,11 @@ SxLibSendNetBufferListsIngress( numNbls, NetBufferLists, &filterReason); - + SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, NetBufferLists, - sendCompleteFlags); + sendCompleteFlags); } else { @@ -79,9 +79,9 @@ SxLibSendNetBufferListsIngress( { nextNbl = curNbl->Next; curNbl->Next = NULL; - + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); - + if(curSourcePort == fwdDetail->SourcePortId) { *curDropNbl = curNbl; @@ -99,7 +99,7 @@ SxLibSendNetBufferListsIngress( numNbls, dropNbl, &filterReason); - + SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, dropNbl, @@ -111,7 +111,7 @@ SxLibSendNetBufferListsIngress( curSourcePort = fwdDetail->SourcePortId; } } - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -121,21 +121,21 @@ SxLibSendNetBufferListsIngress( numNbls, dropNbl, &filterReason); - + SxExtStartCompleteNetBufferListsIngress(Switch, Switch->ExtensionContext, dropNbl, sendCompleteFlags); - } - + } + goto Cleanup; } - + NdisFSendNetBufferLists(Switch->NdisFilterHandle, NetBufferLists, NDIS_DEFAULT_PORT_NUMBER, SendFlags); - + Cleanup: return; } @@ -159,23 +159,23 @@ SxLibSendNetBufferListsEgress( PNET_BUFFER_LIST dropNbl = NULL; PNET_BUFFER_LIST *curDropNbl = &dropNbl; NDIS_STRING filterReason; - + dispatch = NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(ReceiveFlags); sameSource = NDIS_TEST_RECEIVE_FLAG(ReceiveFlags, NDIS_RECEIVE_FLAGS_SWITCH_SINGLE_SOURCE); - + if (Switch->DataFlowState != SxSwitchRunning) { RtlInitUnicodeString(&filterReason, L"Extension Paused"); - + returnFlags = (dispatch) ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0; returnFlags |= NDIS_RETURN_FLAGS_SWITCH_SINGLE_SOURCE; - + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); - + if (sameSource) { sourcePortId = fwdDetail->SourcePortId; - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -185,7 +185,7 @@ SxLibSendNetBufferListsEgress( NumberOfNetBufferLists, NetBufferLists, &filterReason); - + SxExtStartCompleteNetBufferListsEgress(Switch, Switch->ExtensionContext, NetBufferLists, @@ -199,9 +199,9 @@ SxLibSendNetBufferListsEgress( { nextNbl = curNbl->Next; curNbl->Next = NULL; - + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); - + if(curSourcePort == fwdDetail->SourcePortId) { *curDropNbl = curNbl; @@ -219,7 +219,7 @@ SxLibSendNetBufferListsEgress( numNbls, dropNbl, &filterReason); - + SxExtStartCompleteNetBufferListsEgress(Switch, Switch->ExtensionContext, dropNbl, @@ -231,7 +231,7 @@ SxLibSendNetBufferListsEgress( curSourcePort = fwdDetail->SourcePortId; } } - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -241,22 +241,22 @@ SxLibSendNetBufferListsEgress( numNbls, dropNbl, &filterReason); - + SxExtStartCompleteNetBufferListsEgress(Switch, Switch->ExtensionContext, dropNbl, returnFlags); - } - + } + goto Cleanup; } - + NdisFIndicateReceiveNetBufferLists(Switch->NdisFilterHandle, NetBufferLists, NDIS_DEFAULT_PORT_NUMBER, NumberOfNetBufferLists, ReceiveFlags); - + Cleanup: return; } @@ -407,17 +407,17 @@ Cleanup: { *BytesNeeded = bytesNeeded; } - + if (!asyncCompletion) { NdisInterlockedDecrement(&Switch->PendingOidCount); } - + if (oidRequest != NULL) { ExFreePoolWithTag(oidRequest, SxExtAllocationTag); } - + return status; } @@ -429,11 +429,11 @@ SxLibGetSwitchParametersUnsafe( ) { NDIS_STATUS status; - + SwitchParameters->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1; SwitchParameters->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; SwitchParameters->Header.Size = sizeof(NDIS_SWITCH_PARAMETERS); - + status = SxLibIssueOidRequest(Switch, NdisRequestQueryInformation, OID_SWITCH_PARAMETERS, @@ -443,7 +443,7 @@ SxLibGetSwitchParametersUnsafe( 0, 0, NULL); - + return status; } @@ -458,32 +458,32 @@ SxLibGetPortArrayUnsafe( ULONG BytesNeeded = 0; PNDIS_SWITCH_PORT_ARRAY portArray = NULL; ULONG arrayLength = 0; - - do + + do { if (portArray != NULL) { ExFreePoolWithTag(portArray, SxExtAllocationTag); } - + if (BytesNeeded != 0) { arrayLength = BytesNeeded; portArray = ExAllocatePool2(POOL_FLAG_NON_PAGED, arrayLength, SxExtAllocationTag); - + if (portArray == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + portArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1; portArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; portArray->Header.Size = (USHORT)arrayLength; } - + status = SxLibIssueOidRequest(Switch, NdisRequestQueryInformation, OID_SWITCH_PORT_ARRAY, @@ -493,9 +493,9 @@ SxLibGetPortArrayUnsafe( 0, 0, &BytesNeeded); - + } while(status == NDIS_STATUS_INVALID_LENGTH); - + *PortArray = portArray; Cleanup: if (status != NDIS_STATUS_SUCCESS && @@ -503,7 +503,7 @@ Cleanup: { ExFreePoolWithTag(portArray, SxExtAllocationTag); } - + return status; } @@ -518,32 +518,32 @@ SxLibGetNicArrayUnsafe( ULONG BytesNeeded = 0; PNDIS_SWITCH_NIC_ARRAY nicArray = NULL; ULONG arrayLength = 0; - - do + + do { if (nicArray != NULL) { ExFreePoolWithTag(nicArray, SxExtAllocationTag); } - + if (BytesNeeded != 0) { arrayLength = BytesNeeded; nicArray = ExAllocatePool2(POOL_FLAG_NON_PAGED, arrayLength, SxExtAllocationTag); - + if (nicArray == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + nicArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1; nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nicArray->Header.Size = (USHORT)arrayLength; } - + status = SxLibIssueOidRequest(Switch, NdisRequestQueryInformation, OID_SWITCH_NIC_ARRAY, @@ -553,9 +553,9 @@ SxLibGetNicArrayUnsafe( 0, 0, &BytesNeeded); - + } while(status == NDIS_STATUS_INVALID_LENGTH); - + *NicArray = nicArray; Cleanup: if (status != NDIS_STATUS_SUCCESS && @@ -563,7 +563,7 @@ Cleanup: { ExFreePoolWithTag(nicArray, SxExtAllocationTag); } - + return status; } @@ -581,13 +581,13 @@ SxLibGetSwitchPropertyUnsafe( ULONG bytesNeeded = 0; PNDIS_SWITCH_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL; USHORT outputBufferLength = sizeof(NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS); - + propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; propertyParameters.Header.Revision = NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS_REVISION_1; - + propertyParameters.PropertyType = PropertyType; propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1; - + // // For Built-in properties, the ID is unnecessary. // @@ -601,18 +601,18 @@ SxLibGetSwitchPropertyUnsafe( { ASSERT(PropertyType != NdisSwitchPropertyTypeCustom); } - + outputBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, outputBufferLength, SxExtAllocationTag); - + if (outputBuffer == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - - do + + do { if (bytesNeeded != 0) { @@ -622,20 +622,20 @@ SxLibGetSwitchPropertyUnsafe( outputBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, outputBufferLength, SxExtAllocationTag); - + if (outputBuffer == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } } - + if(outputBufferLength >= sizeof(propertyParameters)) { NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters)); - + } - + status = SxLibIssueOidRequest(Switch, NdisRequestMethod, OID_SWITCH_PROPERTY_ENUM, @@ -645,19 +645,19 @@ SxLibGetSwitchPropertyUnsafe( 0, 0, &bytesNeeded); - + } while(status == NDIS_STATUS_INVALID_LENGTH); - -Cleanup: + +Cleanup: if (status != NDIS_STATUS_SUCCESS && outputBuffer != NULL) { ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); outputBuffer = NULL; } - + *SwitchPropertyEnumParameters = outputBuffer; - + return status; } @@ -676,14 +676,14 @@ SxLibGetPortPropertyUnsafe( ULONG bytesNeeded = 0; PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS outputBuffer = NULL; USHORT outputBufferLength = sizeof(NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS); - + propertyParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; propertyParameters.Header.Revision = NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS_REVISION_1; - + propertyParameters.PortId = PortId; propertyParameters.PropertyType = PropertyType; propertyParameters.SerializationVersion = NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1; - + // // For Built-in properties, the ID is unnecessary. // @@ -697,18 +697,18 @@ SxLibGetPortPropertyUnsafe( { ASSERT(PropertyType != NdisSwitchPortPropertyTypeCustom); } - + outputBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, outputBufferLength, SxExtAllocationTag); - + if (outputBuffer == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - - do + + do { if (bytesNeeded != 0) { @@ -718,20 +718,20 @@ SxLibGetPortPropertyUnsafe( outputBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, outputBufferLength, SxExtAllocationTag); - + if (outputBuffer == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } } - + if(outputBufferLength >= sizeof(propertyParameters)) { outputBuffer->Header.Size = outputBufferLength; NdisMoveMemory(outputBuffer, &propertyParameters, sizeof(propertyParameters)); } - + status = SxLibIssueOidRequest(Switch, NdisRequestMethod, OID_SWITCH_PORT_PROPERTY_ENUM, @@ -741,9 +741,9 @@ SxLibGetPortPropertyUnsafe( 0, 0, &bytesNeeded); - + } while(status == NDIS_STATUS_INVALID_LENGTH); - + Cleanup: if (status != NDIS_STATUS_SUCCESS && outputBuffer != NULL) @@ -751,9 +751,9 @@ Cleanup: ExFreePoolWithTag(outputBuffer, SxExtAllocationTag); outputBuffer = NULL; } - + *PortPropertyEnumParameters = outputBuffer; - + return status; } @@ -788,27 +788,27 @@ SxLibIssueNicStatusIndicationUnsafe( NDIS_STATUS_INDICATION statusIndication; NDIS_STATUS_INDICATION wrappedIndication; NDIS_SWITCH_NIC_STATUS_INDICATION nicIndication; - + NdisZeroMemory(&wrappedIndication, sizeof(wrappedIndication)); - + wrappedIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; wrappedIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; wrappedIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; - + wrappedIndication.SourceHandle = Switch->NdisFilterHandle; wrappedIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER; - + wrappedIndication.StatusCode = StatusCode; wrappedIndication.StatusBuffer = StatusBuffer; wrappedIndication.StatusBufferSize = StatusBufferSize; - + NdisZeroMemory(&nicIndication, sizeof(nicIndication)); - + nicIndication.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nicIndication.Header.Revision = NDIS_SWITCH_NIC_STATUS_INDICATION_REVISION_1; nicIndication.Header.Size = NDIS_SIZEOF_SWITCH_NIC_STATUS_REVISION_1; nicIndication.StatusIndication = &wrappedIndication; - + if (IsDestination) { nicIndication.DestinationPortId = PortId; @@ -819,20 +819,20 @@ SxLibIssueNicStatusIndicationUnsafe( nicIndication.SourcePortId = PortId; nicIndication.SourceNicIndex = NicIndex; } - + NdisZeroMemory(&statusIndication, sizeof(statusIndication)); - + statusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; statusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; statusIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; - + statusIndication.SourceHandle = Switch->NdisFilterHandle; statusIndication.PortNumber = NDIS_DEFAULT_PORT_NUMBER; - + statusIndication.StatusCode = NDIS_STATUS_SWITCH_NIC_STATUS; statusIndication.StatusBuffer = &nicIndication; statusIndication.StatusBufferSize = sizeof(nicIndication); - + NdisFIndicateStatus(Switch->NdisFilterHandle, &statusIndication); } diff --git a/network/ndis/extension/base/SxLibrary.h b/network/ndis/extension/base/SxLibrary.h index 2d9a30af..7071ab0c 100644 --- a/network/ndis/extension/base/SxLibrary.h +++ b/network/ndis/extension/base/SxLibrary.h @@ -18,32 +18,32 @@ Abstract: /*++ SxLibSendNetBufferListsIngress - + Routine Description: This function is called to forward NBLs on ingress. The extension MUST call this function, or call SxLibCompleteNetBufferListsIngress for every NBL in NetBufferLists, - recieved in SxExtStartNetBufferListsIngress. - + received in SxExtStartNetBufferListsIngress. + This function can also be called to inject NBLs. If there are NBLs in NetBufferLists that are initiated by the extension, NumInjectedNetBufferLists must be the number of new NBLs. - + Arguments: Switch - the Switch context - + NetBufferLists - the NBLs to send - + SendFlags - the SendFlags equivalent to NDIS flags for NdisFSendNetBufferLists - + NumInjectedNetBufferLists - the number of NBLs in NetBufferLists initiated by the extension - + Return Value: VOID - + --*/ VOID SxLibSendNetBufferListsIngress( @@ -53,31 +53,31 @@ SxLibSendNetBufferListsIngress( _In_ ULONG NumInjectedNetBufferLists ); - + /*++ SxLibSendNetBufferListsEgress - + Routine Description: This function is called to forward NBLs on egress. The extension MUST call this function, or call SxLibCompleteNetBufferListsEgress for every NBL in NetBufferLists - recieved in SxExtStartNetBufferListsEgress. - + received in SxExtStartNetBufferListsEgress. + Arguments: Switch - the Switch context - + NetBufferLists - the NBLs to send - + NumberOfNetBufferLists - the number of NBLs in NetBufferLists - + ReceiveFlags - the ReceiveFlags equivalent to NDIS flags for NdisFIndicateReceiveNetBufferLists - + Return Value: VOID - + --*/ VOID SxLibSendNetBufferListsEgress( @@ -87,28 +87,28 @@ SxLibSendNetBufferListsEgress( _In_ ULONG ReceiveFlags ); - + /*++ SxLibCompleteNetBufferListsEgress - + Routine Description: This function is called to complete NBLs on egress. - The extension MUST call this function for all NBLs recieved + The extension MUST call this function for all NBLs received in SxExtStartCompleteNetBufferListsEgress. - + Arguments: Switch - the Switch context - + NetBufferLists - the NBLs to send - + ReturnFlags - the ReceiveFlags equivalent to NDIS flags for NdisFReturnNetBufferLists - + Return Value: VOID - + --*/ VOID SxLibCompleteNetBufferListsEgress( @@ -120,25 +120,25 @@ SxLibCompleteNetBufferListsEgress( /*++ SxLibCompleteNetBufferListsIngress - + Routine Description: This function is called to complete NBLs on ingress. The extension MUST call this function, or - SxLibCompletedInjectedNetBufferLists for all NBLs recieved in + SxLibCompletedInjectedNetBufferLists for all NBLs received in SxExtStartCompleteNetBufferListsEgress. - + Arguments: Switch - the Switch context - + NetBufferLists - the NBLs to send - + SendCompleteFlags - the ReceiveFlags equivalent to NDIS flags for NdisFSendNetBufferListsComplete - + Return Value: VOID - + --*/ VOID SxLibCompleteNetBufferListsIngress( @@ -147,32 +147,32 @@ SxLibCompleteNetBufferListsIngress( _In_ ULONG SendCompleteFlags ); - + /*++ SxLibCompletedInjectedNetBufferLists - + Routine Description: This function is called after completing NBLs injected by the extension. - + Arguments: Switch - the Switch context - + NumInjectedNetBufferLists - the number of NBLs completed - + Return Value: VOID - + --*/ VOID SxLibCompletedInjectedNetBufferLists( _In_ PSX_SWITCH_OBJECT Switch, _In_ ULONG NumInjectedNetBufferLists - ); + ); + - /*++ SxLibIssueOidRequest @@ -185,12 +185,12 @@ Routine Description: NOTE: this assumes that the calling routine ensures validity of the filter handle until this returns. - + This function can only be called at PASSIVE_LEVEL. Arguments: - Switch - pointer to our switch object. + SxSwitch - pointer to our switch object. RequestType - NdisRequest[Set|Query|method]Information. @@ -203,8 +203,8 @@ Arguments: OutputBufferLength - valid only for method request. MethodId - valid only for method request. - - Timeout - The timeout in seconds for the OID. + + Timeout - The timeout in seconds for the OID. BytesNeeded - place to return bytes read/written. @@ -225,88 +225,88 @@ SxLibIssueOidRequest( _In_ UINT Timeout, _Out_ PULONG BytesNeeded ); - + /*++ SxLibGetSwitchParametersUnsafe - + Routine Description: This function is called to get the current state of the switch. - + Arguments: Switch - the Switch context - + SwitchParameters - the returned switch parameters - + Return Value: NDIS_STATUS_SUCCESS - if SwitchParameters was successfully returned - + NDIS_STATUS_*** - otherwise - ---*/ + +--*/ NDIS_STATUS SxLibGetSwitchParametersUnsafe( _In_ PSX_SWITCH_OBJECT Switch, _Out_ PNDIS_SWITCH_PARAMETERS SwitchParameters ); - + /*++ SxLibGetPortArrayUnsafe - + Routine Description: This function is called to get the current array of ports. - - NOTE: It is necessary to synchonize this with SxExtPortCreate + + NOTE: It is necessary to synchronize this with SxExtPortCreate and SxExtPortTeardown. - + Arguments: Switch - the Switch context - + PortArray - the returned port array - + Return Value: NDIS_STATUS_SUCCESS - if PortArray was successfully allocated and returned - + NDIS_STATUS_*** - otherwise - + --*/ NDIS_STATUS SxLibGetPortArrayUnsafe( _In_ PSX_SWITCH_OBJECT Switch, _Out_ PNDIS_SWITCH_PORT_ARRAY *PortArray - ); + ); + - /*++ SxLibGetNicArrayUnsafe - + Routine Description: This function is called to get the current array of NICs. - - NOTE: It is necessary to synchonize this with SxExtNicConnect + + NOTE: It is necessary to synchronize this with SxExtNicConnect and SxExtNicDisconnect. - + Arguments: - Switch - the Switch context - + SxSwitch - the Switch context + NicArray - the returned NIC array - + Return Value: NDIS_STATUS_SUCCESS - if NicArray was successfully allocated and returned - + NDIS_STATUS_*** - otherwise - + --*/ NDIS_STATUS SxLibGetNicArrayUnsafe( @@ -317,32 +317,30 @@ SxLibGetNicArrayUnsafe( /*++ SxLibGetSwitchPropertyUnsafe - + Routine Description: This function is called to get the current array of the switch property queried. - - NOTE: It is necessary to synchonize this with SxExtAddSwitchProperty + + NOTE: It is necessary to synchronize this with SxExtAddSwitchProperty and SxExtDeleteSwitchProperty. - + Arguments: Switch - the Switch context - + PropertyType - the PropertyType to query for - + PropertyId - the GUID of the property (from mof file) - - PropertyVersion - the version of the property - + SwitchPropertyEnumParameters - the returned property enum - + Return Value: NDIS_STATUS_SUCCESS - if SwitchPropertyEnumParameters was successfully allocated and returned - + NDIS_STATUS_*** - otherwise - + --*/ NDIS_STATUS SxLibGetSwitchPropertyUnsafe( @@ -355,32 +353,32 @@ SxLibGetSwitchPropertyUnsafe( /*++ SxLibGetPortPropertyUnsafe - + Routine Description: This function is called to get the current array of the switch property queried. - - NOTE: It is necessary to synchonize this with SxExtAddPortProperty + + NOTE: It is necessary to synchronize this with SxExtAddPortProperty and SxExtDeletePortProperty. - + Arguments: Switch - the Switch context - + PortId - the port to query from - + PropertyType - the PropertyType to query for - + PropertyId - the GUID of the property (from mof file) - + PortPropertyEnumParameters - the returned property enum - + Return Value: NDIS_STATUS_SUCCESS - if PortPropertyEnumParameters was successfully allocated and returned - + NDIS_STATUS_*** - otherwise - + --*/ NDIS_STATUS SxLibGetPortPropertyUnsafe( @@ -394,25 +392,25 @@ SxLibGetPortPropertyUnsafe( /*++ SxLibRevokeVfUnsafe - + Routine Description: This function is called revoke the VF assignment for the given VM. - + NOTE: This must be synchonized with SxExtNicConnect and SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic must have been successfully called. - + Arguments: Switch - the Switch context - + PortId - the port the VM is connected to - + Return Value: VOID - ---*/ + +--*/ VOID SxLibRevokeVfUnsafe( _In_ PSX_SWITCH_OBJECT Switch, @@ -422,35 +420,35 @@ SxLibRevokeVfUnsafe( /*++ SxLibIssueNicStatusIndicationUnsafe - + Routine Description: This function is called issue a NIC status indication. - + NOTE: This must be synchonized with SxExtNicConnect and SxExtNicDisconnect for the PortId given, and ReferenceSwitchNic must have been successfully called. - + Arguments: Switch - the Switch context - + StatusCode - the status code to indicate - + PortId - the port to indicate to/from - + NicIndex - the nic index to indicate to/from - + IsDestination - TRUE if PortId/NicIndex is destination info FALSE if PortId/NicIndex is source info - + StatusBuffer - the StatusBuffer for the indication - + StatusBufferSize - the size of StatusBuffer - + Return Value: VOID - ---*/ + +--*/ VOID SxLibIssueNicStatusIndicationUnsafe( _In_ PSX_SWITCH_OBJECT Switch, @@ -461,4 +459,4 @@ SxLibIssueNicStatusIndicationUnsafe( _In_opt_ PVOID StatusBuffer, _In_ ULONG StatusBufferSize ); - + diff --git a/network/ndis/extension/samples/forward/MSForwardExtPolicy.mof b/network/ndis/extension/samples/forward/MSForwardExtPolicy.mof index 88105b2f..7d719ac3 100644 --- a/network/ndis/extension/samples/forward/MSForwardExtPolicy.mof +++ b/network/ndis/extension/samples/forward/MSForwardExtPolicy.mof @@ -6,9 +6,9 @@ // #pragma namespace("\\\\.\\root\\virtualization\\v2") -[ Dynamic, +[ Dynamic, UUID("EB29F0F2-F5DC-45C6-81BB-3CD9F219BBBB"), - ExtensionId("37d9eae6-5bae-48c5-bff1-63a7cdd7e4f4"), + ExtensionId("37d9eae6-5bae-48c5-bff1-63a7cdd7e4f4"), Provider("VmmsWmiInstanceAndMethodProvider"), Locale(0x409), InterfaceVersion("1"), @@ -16,7 +16,7 @@ DisplayName("MSForwardExt MAC Address Policy") : Amended, Description("Source MAC Addresses to allow sends on MSForwardExt.") : Amended] class MSForwardExt_MacAddressRule : Msvm_EthernetSwitchFeatureSettingData { - + // // MAC Address set on switch to allow sends from. // @@ -29,4 +29,4 @@ class MSForwardExt_MacAddressRule : Msvm_EthernetSwitchFeatureSettingData { Description ( "Mac Address") : Amended] uint8 MacAddress[] = {}; -}; +}; diff --git a/network/ndis/extension/samples/forward/MSForwardExtPolicyStatus.mof b/network/ndis/extension/samples/forward/MSForwardExtPolicyStatus.mof index c9d509e8..c8e32760 100644 --- a/network/ndis/extension/samples/forward/MSForwardExtPolicyStatus.mof +++ b/network/ndis/extension/samples/forward/MSForwardExtPolicyStatus.mof @@ -6,9 +6,9 @@ // #pragma namespace("\\\\.\\root\\virtualization\\v2") -[ Dynamic, +[ Dynamic, UUID("A3E2AFF5-E6FA-4E52-AB74-13250BF7E8CF"), - ExtensionId("37d9eae6-5bae-48c5-bff1-63a7cdd7e4f4"), + ExtensionId("37d9eae6-5bae-48c5-bff1-63a7cdd7e4f4"), Provider("VmmsWmiInstanceAndMethodProvider"), Applicability("2"), Locale(0x409), @@ -17,7 +17,7 @@ DisplayName("MSForwardExt MAC Address Policy Status") : Amended, Description("The current array of PortIds with policy set to allow sends") : Amended] class MSForwardExt_MacAddressRuleStatus : Msvm_EthernetSwitchData { - + // // Array of PortId's currently allowing sends. // @@ -28,4 +28,4 @@ class MSForwardExt_MacAddressRuleStatus : Msvm_EthernetSwitchData { Description ( "Currently Allowed Port Ids") : Amended] uint32 AllowedPortIds[] = {}; -}; +}; diff --git a/network/ndis/extension/samples/forward/MsForwardExt.c b/network/ndis/extension/samples/forward/MsForwardExt.c index cabd6401..69583156 100644 --- a/network/ndis/extension/samples/forward/MsForwardExt.c +++ b/network/ndis/extension/samples/forward/MsForwardExt.c @@ -50,15 +50,15 @@ const NDIS_SWITCH_OBJECT_ID MacAddressPolicyStatusGuid = { 0x4E52, {0xAB, 0x74, 0x13, 0x25, 0x0B, 0xF7, 0xE8, 0xCF} }; - - + + NDIS_STATUS SxExtInitialize() /*++ - + Routine Description: No global information needed. - + --*/ { return NDIS_STATUS_SUCCESS; @@ -68,10 +68,10 @@ Routine Description: VOID SxExtUninitialize() /*++ - + Routine Description: No global information needed. - + --*/ { return; @@ -85,41 +85,41 @@ SxExtCreateSwitch( PNDIS_HANDLE *ExtensionContext ) /*++ - + Routine Description: This function allocated the switch context, and initializes its necessary members. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PMSFORWARD_CONTEXT switchContext; - + switchContext = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(MSFORWARD_CONTEXT), SxExtAllocationTag); - + if (switchContext == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + NdisZeroMemory(switchContext, sizeof(MSFORWARD_CONTEXT)); InitializeListHead(&switchContext->NicList); InitializeListHead(&switchContext->PropertyList); - + switchContext->DispatchLock = NdisAllocateRWLock(Switch->NdisFilterHandle); if (switchContext->DispatchLock == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + switchContext->IsInitialRestart = TRUE; - + *ExtensionContext = (NDIS_HANDLE)switchContext; - + Cleanup: if (status != NDIS_STATUS_SUCCESS) { @@ -140,17 +140,17 @@ SxExtDeleteSwitch( NDIS_HANDLE ExtensionContext ) /*++ - + Routine Description: This function deletes the switch by freeing all memory previously allocated. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; - + UNREFERENCED_PARAMETER(Switch); - + MsForwardClearNicListUnsafe(switchContext); MsForwardClearPropertyListUnsafe(switchContext); NdisFreeRWLock(switchContext->DispatchLock); @@ -167,7 +167,7 @@ SxExtActivateSwitch( { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; MsForwardInitSwitch(Switch, switchContext); - + return; } @@ -179,7 +179,7 @@ SxExtRestartSwitch( NDIS_HANDLE ExtensionContext ) /*++ - + Routine Description: This function initializes the switch if it is the first restart. First it queries all of the MAC addresses set as custom @@ -188,7 +188,7 @@ Routine Description: Then it queries the NIC list and verifies it can support all of the NICs currently connected to the switch, and adds the NICs to the NIC list. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; @@ -198,12 +198,12 @@ Routine Description: if (switchContext->IsInitialRestart) { status = SxLibGetSwitchParametersUnsafe(Switch, &switchParameters); - + if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } - + if (switchParameters.IsActive) { status = MsForwardInitSwitch(Switch, switchContext); @@ -212,11 +212,11 @@ Routine Description: goto Cleanup; } } - + switchContext->IsInitialRestart = FALSE; } - -Cleanup: + +Cleanup: return status; } @@ -228,15 +228,15 @@ SxExtPauseSwitch( NDIS_HANDLE ExtensionContext ) /*++ - + Routine Description: No pause funtionality required. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + return; } @@ -249,16 +249,16 @@ SxExtCreatePort( PNDIS_SWITCH_PORT_PARAMETERS Port ) /*++ - + Routine Description: This extension does not track ports, only NICs. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return NDIS_STATUS_SUCCESS; } @@ -271,16 +271,16 @@ SxExtUpdatePort( PNDIS_SWITCH_PORT_PARAMETERS Port ) /*++ - + Routine Description: This extension does not track ports, only NICs. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return; } @@ -293,18 +293,18 @@ SxExtCreateNic( PNDIS_SWITCH_NIC_PARAMETERS Nic ) /*++ - + Routine Description: Allocate NIC, add to NIC list, and correlate with policy. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + // // Wait for lists to be initialized. // @@ -312,9 +312,9 @@ Routine Description: { NdisMSleep(100); } - + NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); - + status = MsForwardAddNicUnsafe(switchContext, Nic->PermanentMacAddress, Nic->PortId, @@ -322,9 +322,9 @@ Routine Description: Nic->NicType, FALSE); - + NdisReleaseRWLock(switchContext->DispatchLock, &lockState); - + return status; } @@ -337,18 +337,18 @@ SxExtConnectNic( PNDIS_SWITCH_NIC_PARAMETERS Nic ) /*++ - + Routine Description: Mark already created NIC as connected. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; PMSFORWARD_NIC_LIST_ENTRY nicEntry = NULL; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + // // Wait for lists to be initialized. // @@ -356,7 +356,7 @@ Routine Description: { NdisMSleep(100); } - + NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); if (Nic->NicType == NdisSwitchNicTypeExternal && Nic->NicIndex != 0 && @@ -372,7 +372,7 @@ Routine Description: nicEntry = MsForwardFindNicByPortIdUnsafe(switchContext, Nic->PortId, Nic->NicIndex); - + if(nicEntry != NULL) { nicEntry->Connected = TRUE; @@ -395,21 +395,21 @@ SxExtUpdateNic( PNDIS_SWITCH_NIC_PARAMETERS Nic ) /*++ - + Routine Description: This extension doesn't use any of the fields that can be updated. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return; } -_Use_decl_annotations_ +_Use_decl_annotations_ VOID SxExtDisconnectNic( PSX_SWITCH_OBJECT Switch, @@ -417,18 +417,18 @@ SxExtDisconnectNic( PNDIS_SWITCH_NIC_PARAMETERS Nic ) /*++ - + Routine Description: Mark already created NIC as disconnected. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; PMSFORWARD_NIC_LIST_ENTRY nicEntry = NULL; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + // // Wait for lists to be initialized. // @@ -436,12 +436,12 @@ Routine Description: { NdisMSleep(100); } - + NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); if (Nic->NicType == NdisSwitchNicTypeExternal) { if (Nic->NicIndex == switchContext->ExternalNicIndex) - { + { --(switchContext->NumDestinations); switchContext->ExternalNicConnected = FALSE; } @@ -451,7 +451,7 @@ Routine Description: nicEntry = MsForwardFindNicByPortIdUnsafe(switchContext, Nic->PortId, Nic->NicIndex); - + if(nicEntry != NULL) { nicEntry->Connected = FALSE; @@ -466,7 +466,7 @@ Routine Description: NdisReleaseRWLock(switchContext->DispatchLock, &lockState); } - + _Use_decl_annotations_ VOID SxExtDeleteNic( @@ -475,18 +475,18 @@ SxExtDeleteNic( PNDIS_SWITCH_NIC_PARAMETERS Nic ) /*++ - + Routine Description: Delete created NIC, free related memory and remove from NIC list. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + // // Wait for lists to be initialized. // @@ -494,7 +494,7 @@ Routine Description: { NdisMSleep(100); } - + NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); if (Nic->NicType == NdisSwitchNicTypeExternal && Nic->NicIndex == switchContext->ExternalNicIndex) @@ -523,10 +523,10 @@ SxExtTeardownPort( PNDIS_SWITCH_PORT_PARAMETERS Port ) /*++ - + Routine Description: This extension does not track port state. - + --*/ { UNREFERENCED_PARAMETER(Switch); @@ -537,16 +537,16 @@ Routine Description: _Use_decl_annotations_ VOID -SxExtDeletePort( +SxExtDeletePort( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_PORT_PARAMETERS Port ) /*++ - + Routine Description: This extension does not track port state. - + --*/ { UNREFERENCED_PARAMETER(Switch); @@ -555,9 +555,9 @@ Routine Description: } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS -SxExtSaveNic( +SxExtSaveNic( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState, @@ -565,63 +565,63 @@ SxExtSaveNic( PULONG BytesNeeded ) /*++ - + Routine Description: This extension does not save any data. - + --*/ -{ +{ UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + *BytesWritten = 0; *BytesNeeded = 0; return NDIS_STATUS_SUCCESS; } -_Use_decl_annotations_ +_Use_decl_annotations_ VOID -SxExtSaveNicComplete( +SxExtSaveNicComplete( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState ) /*++ - + Routine Description: This extension does not save any data. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + return; } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS -SxExtNicRestore( +SxExtNicRestore( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState, PULONG BytesRestored ) /*++ - + Routine Description: This extension does not save any data. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + *BytesRestored = 0; return NDIS_STATUS_SUCCESS; } @@ -629,22 +629,22 @@ Routine Description: _Use_decl_annotations_ VOID -SxExtNicRestoreComplete( +SxExtNicRestoreComplete( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState ) /*++ - + Routine Description: This extension does not save any data. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + return; } @@ -657,12 +657,12 @@ SxExtAddSwitchProperty( PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty ) /*++ - + Routine Description: This extension enforces one custom switch policy. The function verifies the switch property is our MAC policy and then adds it to the property list. - + --*/ { NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; @@ -670,14 +670,14 @@ Routine Description: PMSFORWARD_MAC_ADDRESS_POLICY macPolicy; PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + if (SwitchProperty->PropertyType != NdisSwitchPropertyTypeCustom) { goto Cleanup; } - + // // Check if MAC Address Policy for this extension. // @@ -687,17 +687,17 @@ Routine Description: { goto Cleanup; } - + if (SwitchProperty->PropertyVersion != MAC_ADDRESS_POLICY_VERSION) { goto Cleanup; } - + if (SwitchProperty->SerializationVersion != MAC_ADDRESS_POLICY_SERIALIZATION_VERSION) { goto Cleanup; } - + // // Wait for lists to be initialized. // @@ -705,31 +705,31 @@ Routine Description: { NdisMSleep(100); } - + customPolicy = NDIS_SWITCH_PROPERTY_PARAMETERS_GET_PROPERTY(SwitchProperty); macPolicy = NDIS_SWITCH_PROPERTY_CUSTOM_GET_BUFFER(customPolicy); - + if (macPolicy->MacAddressLength != 6) { status = NDIS_STATUS_DATA_NOT_ACCEPTED; - } + } else { NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); - + status = MsForwardAddMacPolicyUnsafe(switchContext, macPolicy, &SwitchProperty->PropertyInstanceId); - + NdisReleaseRWLock(switchContext->DispatchLock, &lockState); } - + Cleanup: return status; } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS SxExtUpdateSwitchProperty( PSX_SWITCH_OBJECT Switch, @@ -737,15 +737,15 @@ SxExtUpdateSwitchProperty( PNDIS_SWITCH_PROPERTY_PARAMETERS SwitchProperty ) /*++ - + Routine Description: This extension enforces one custom switch policy, but does not allow updates for that policy. - + --*/ { NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; - + UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); @@ -753,7 +753,7 @@ Routine Description: { goto Cleanup; } - + // // Check if MAC Address Policy for this extension. // @@ -763,19 +763,19 @@ Routine Description: { goto Cleanup; } - + if (SwitchProperty->PropertyVersion != MAC_ADDRESS_POLICY_VERSION) { goto Cleanup; } - + if (SwitchProperty->SerializationVersion != MAC_ADDRESS_POLICY_SERIALIZATION_VERSION) { goto Cleanup; } status = NDIS_STATUS_DATA_NOT_ACCEPTED; - + Cleanup: return status; } @@ -789,25 +789,25 @@ SxExtDeleteSwitchProperty( PNDIS_SWITCH_PROPERTY_DELETE_PARAMETERS SwitchProperty ) /*++ - + Routine Description: This extension enforces one custom switch policy. The function verifies the switch property is our MAC policy and then deletes it from the property list. - + --*/ { BOOLEAN delete = FALSE; PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; LOCK_STATE_EX lockState; - + UNREFERENCED_PARAMETER(Switch); - + if (SwitchProperty->PropertyType != NdisSwitchPropertyTypeCustom) { goto Cleanup; } - + // // Check if MAC Address Policy for this extension. // @@ -817,7 +817,7 @@ Routine Description: { goto Cleanup; } - + // // Wait for lists to be initialized. // @@ -825,23 +825,23 @@ Routine Description: { NdisMSleep(100); } - - + + delete = TRUE; NdisAcquireRWLockWrite(switchContext->DispatchLock, &lockState, 0); - + MsForwardDeleteMacPolicyUnsafe(switchContext, &SwitchProperty->PropertyInstanceId); - + NdisReleaseRWLock(switchContext->DispatchLock, &lockState); - + Cleanup: return delete; } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS SxExtAddPortProperty( PSX_SWITCH_OBJECT Switch, @@ -849,20 +849,20 @@ SxExtAddPortProperty( PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty ) /*++ - + Routine Description: This extension does not enforce VLAN. Because of this the extension fails the adding of these policies. - + !! REAL FORWARDING EXTENSIONS SHOULD SUPPORT THESE PROPERTIES !! - + --*/ { NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; - + UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + switch(PortProperty->PropertyType) { case NdisSwitchPortPropertyTypeCustom: @@ -870,14 +870,14 @@ Routine Description: // No Custom Port Properties. // break; - + case NdisSwitchPortPropertyTypeSecurity: // // This extension does need to look at security policy, pass it down. // An extension must always pass through Hyper-V security policy. // break; - + case NdisSwitchPortPropertyTypeVlan: // // Forwarding extensions must either enforce VLAN, or fail @@ -886,7 +886,7 @@ Routine Description: // status = NDIS_STATUS_DATA_NOT_ACCEPTED; break; - + case NdisSwitchPortPropertyTypeProfile: // // No Processing of Port Profile. @@ -897,7 +897,7 @@ Routine Description: return status; } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS SxExtUpdatePortProperty( PSX_SWITCH_OBJECT Switch, @@ -905,20 +905,20 @@ SxExtUpdatePortProperty( PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS PortProperty ) /*++ - + Routine Description: This extension does not enforce VLAN. Because of this the extension fails the updating of these policies. - + !! REAL FORWARDING EXTENSIONS SHOULD SUPPORT THESE PROPERTIES !! - + --*/ { NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; - + UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + switch(PortProperty->PropertyType) { case NdisSwitchPortPropertyTypeCustom: @@ -926,14 +926,14 @@ Routine Description: // No Custom Port Properties. // break; - + case NdisSwitchPortPropertyTypeSecurity: // // This extension does need to look at security policy, pass it down. // An extension must always pass through Hyper-V security policy. // break; - + case NdisSwitchPortPropertyTypeVlan: // // Forwarding extensions must either enforce VLAN, or fail @@ -942,7 +942,7 @@ Routine Description: // status = NDIS_STATUS_DATA_NOT_ACCEPTED; break; - + case NdisSwitchPortPropertyTypeProfile: // // No Processing of Port Profile. @@ -961,21 +961,21 @@ SxExtDeletePortProperty( PNDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS PortProperty ) /*++ - + Routine Description: This extension does not enforce VLAN. These policies are policies that should be supported by this extension, so it returns TRUE to complete the deletion. - + !! REAL FORWARDING EXTENSIONS SHOULD SUPPORT THESE PROPERTIES !! - + --*/ { BOOLEAN delete = FALSE; - + UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + switch(PortProperty->PropertyType) { case NdisSwitchPortPropertyTypeCustom: @@ -983,14 +983,14 @@ Routine Description: // No Custom Port Properties. // break; - + case NdisSwitchPortPropertyTypeSecurity: // // This extension does need to look at security policy, pass it down. // An extension must always pass through Hyper-V security policy. // break; - + case NdisSwitchPortPropertyTypeVlan: // // Forwarding extensions must either enforce VLAN, or fail @@ -999,7 +999,7 @@ Routine Description: // delete = TRUE; break; - + case NdisSwitchPortPropertyTypeProfile: // // No Processing of Port Profile. @@ -1020,11 +1020,11 @@ SxExtQuerySwitchFeatureStatus( PULONG BytesNeeded ) /*++ - + Routine Description: This extension reports the status of its custom MAC policy by returning the list of PortId's currently allowing sends. - + --*/ { BOOLEAN consumed = FALSE; @@ -1041,26 +1041,26 @@ Routine Description: PNDIS_SWITCH_PORT_ID portIdArray; ULONG arrayIndex = 0; ULONG customBufferLength = 0; - + UNREFERENCED_PARAMETER(Switch); - + if (SwitchFeatureStatus->FeatureStatusType != NdisSwitchFeatureStatusTypeCustom) { goto Cleanup; } - + if (!RtlEqualMemory(&SwitchFeatureStatus->FeatureStatusId, &MacAddressPolicyStatusGuid, sizeof(NDIS_SWITCH_OBJECT_ID))) { goto Cleanup; } - + if (SwitchFeatureStatus->SerializationVersion != MAC_ADDRESS_POLICY_STATUS_SERIALIZATION_VERSION) { goto Cleanup; } - + // // Wait for lists to be initialized. // @@ -1068,52 +1068,52 @@ Routine Description: { NdisMSleep(100); } - + NdisAcquireRWLockRead(switchContext->DispatchLock, &lockState, 0); lockHeld = TRUE; - + if (switchContext->ExternalPortId != NDIS_SWITCH_DEFAULT_PORT_ID) { ++numAllowedSourcePorts; } - + if (!IsListEmpty(nicList)) { curEntry = nicList->Flink; - + do { nic = CONTAINING_RECORD(curEntry, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + if (nic->AllowSends) { ++numAllowedSourcePorts; } curEntry = curEntry->Flink; - + } while(curEntry != nicList); } - + customBufferLength = sizeof(MSFORWARD_MAC_ADDRESS_POLICY_STATUS) + (sizeof(NDIS_SWITCH_PORT_ID) * numAllowedSourcePorts); sizeNeeded = NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_PARAMETERS_REVISION_1 + NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_CUSTOM_REVISION_1 + customBufferLength; - + consumed = TRUE; - + if (SwitchFeatureStatus->FeatureStatusBufferLength < sizeof(NDIS_SWITCH_FEATURE_STATUS_CUSTOM)) { *BytesNeeded = sizeNeeded; goto Cleanup; } - + customStatusBuffer = (PNDIS_SWITCH_FEATURE_STATUS_CUSTOM) (((PUINT8)SwitchFeatureStatus) + SwitchFeatureStatus->FeatureStatusBufferOffset); - + if (customStatusBuffer->Header.Type != NDIS_OBJECT_TYPE_DEFAULT || customStatusBuffer->Header.Revision != NDIS_SWITCH_FEATURE_STATUS_CUSTOM_REVISION_1 || customStatusBuffer->Header.Size != NDIS_SIZEOF_NDIS_SWITCH_FEATURE_STATUS_CUSTOM_REVISION_1) @@ -1121,42 +1121,42 @@ Routine Description: consumed = FALSE; goto Cleanup; } - - - + + + if (customStatusBuffer->FeatureStatusCustomBufferLength < customBufferLength) { *BytesNeeded = sizeNeeded; goto Cleanup; } - + macAddressPolicyBuffer = (PMSFORWARD_MAC_ADDRESS_POLICY_STATUS) (((PUINT8)customStatusBuffer) + customStatusBuffer->FeatureStatusCustomBufferOffset); - + macAddressPolicyBuffer->PortArrayLength = numAllowedSourcePorts; macAddressPolicyBuffer->PortArrayOffset = sizeof(MSFORWARD_MAC_ADDRESS_POLICY_STATUS); - + portIdArray = (PNDIS_SWITCH_PORT_ID) (((PUINT8)macAddressPolicyBuffer) + macAddressPolicyBuffer->PortArrayOffset); - - + + if (switchContext->ExternalPortId != NDIS_SWITCH_DEFAULT_PORT_ID) { portIdArray[arrayIndex] = switchContext->ExternalPortId; ++arrayIndex; } - + if (!IsListEmpty(nicList)) { curEntry = nicList->Flink; - + do { nic = CONTAINING_RECORD(curEntry, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + if (nic->AllowSends) { portIdArray[arrayIndex] = nic->PortId; @@ -1164,7 +1164,7 @@ Routine Description: } curEntry = curEntry->Flink; - + } while(curEntry != nicList); } @@ -1178,7 +1178,7 @@ Cleanup: return consumed; } - + _Use_decl_annotations_ BOOLEAN @@ -1189,17 +1189,17 @@ SxExtQueryPortFeatureStatus( PULONG BytesNeeded ) /*++ - + Routine Description: This extension has no custom port properties. - + --*/ { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(PortFeatureStatus); UNREFERENCED_PARAMETER(BytesNeeded); - + return FALSE; } @@ -1216,24 +1216,24 @@ SxExtProcessNicRequest( PNDIS_SWITCH_NIC_INDEX DestinationNicIndex ) /*++ - + Routine Description: - The only NIC request this extension cares about is + The only NIC request this extension cares about is OID_NIC_SWITCH_ALLOCATE_VF. We must fail all VF allocations so that traffic flows through the extension and we can enforce policy. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; - + UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SourcePortId); UNREFERENCED_PARAMETER(SourceNicIndex); UNREFERENCED_PARAMETER(DestinationPortId); UNREFERENCED_PARAMETER(DestinationNicIndex); - + // // Do not allow VF allocations, as all VM traffic must flow // through our extension. @@ -1243,7 +1243,7 @@ Routine Description: { status = NDIS_STATUS_FAILURE; } - + return status; } @@ -1261,11 +1261,11 @@ SxExtProcessNicRequestComplete( NDIS_STATUS Status ) /*++ - + Routine Description: This function will never be called because we do not redirect or edit any NIC requests. - + --*/ { UNREFERENCED_PARAMETER(Switch); @@ -1276,13 +1276,13 @@ Routine Description: UNREFERENCED_PARAMETER(DestinationPortId); UNREFERENCED_PARAMETER(DestinationNicIndex); UNREFERENCED_PARAMETER(Status); - + // // This function should never be called as we don't set any // source/destination info in SxExtProcessNicRequest. // ASSERT(FALSE); - + return Status; } @@ -1297,11 +1297,11 @@ SxExtProcessNicStatus( NDIS_SWITCH_NIC_INDEX SourceNicIndex ) /*++ - + Routine Description: This extension does not need to process any status indications. - + --*/ { UNREFERENCED_PARAMETER(Switch); @@ -1309,7 +1309,7 @@ Routine Description: UNREFERENCED_PARAMETER(StatusIndication); UNREFERENCED_PARAMETER(SourcePortId); UNREFERENCED_PARAMETER(SourceNicIndex); - + return NDIS_STATUS_SUCCESS; } @@ -1323,7 +1323,7 @@ SxExtStartNetBufferListsIngress( ULONG SendFlags ) /*++ - + Routine Description: The function sets the destination lists of the NBLs forwarded through the switch. @@ -1331,13 +1331,13 @@ Routine Description: Internal NIC, or NICs with MAC Policy set. The extension determines the source by searching for the source MAC address in the NIC list. - + The extension sets destinations by looking at the destination MAC address. If the destination MAC address is a multicast or broadcast address, the extension broadcasts the NBL to all ports, except the source. If the destination MAC is a VM, the extension sets the VM as the destitation. Otherwise the extension sets the External port as the destination. - + --*/ { PMSFORWARD_CONTEXT switchContext = (PMSFORWARD_CONTEXT)ExtensionContext; @@ -1368,13 +1368,13 @@ Routine Description: PNET_BUFFER_LIST nativeForwardedNbls = NULL; PNET_BUFFER_LIST *nextExtForwardNbl = &extForwardedNbls; PNET_BUFFER_LIST *nextNativeForwardedNbl = &nativeForwardedNbls; - + dispatch = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_DISPATCH_LEVEL); sameSource = NDIS_TEST_SEND_FLAG(SendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE); - + sendCompleteFlags |= (dispatch) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0; SendFlags |= NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP; - + // // Take DispatchLock so no NICs disconnect while we're setting destinations. // @@ -1384,9 +1384,9 @@ Routine Description: fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(NetBufferLists); sourcePort = fwdDetail->SourcePortId; sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex; - + sendCompleteFlags |= NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE; - + sourceNicEntry = MsForwardFindNicByPortIdUnsafe(switchContext, sourcePort, sourceIndex); @@ -1398,11 +1398,11 @@ Routine Description: { ++numDropNbls; } - - *nextDropNbl = NetBufferLists; - + + *nextDropNbl = NetBufferLists; + RtlInitUnicodeString(&filterReason, L"Blocked by Source MAC Policy"); - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -1412,10 +1412,10 @@ Routine Description: numDropNbls, dropNbl, &filterReason); - + goto Cleanup; } - + // // If nicEntry is not found, and is not external port, // we must have failed to allocate this port. @@ -1428,11 +1428,11 @@ Routine Description: { ++numDropNbls; } - + *nextDropNbl = NetBufferLists; - + RtlInitUnicodeString(&filterReason, L"Low Resources"); - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -1442,11 +1442,11 @@ Routine Description: numDropNbls, dropNbl, &filterReason); - + goto Cleanup; - } + } } - + // // Split NBL list into NBLs to be forwarded by us, and those that require // native forwarding. @@ -1467,14 +1467,14 @@ Routine Description: nextExtForwardNbl = &(curNbl->Next); } } - + for (curNbl = extForwardedNbls; curNbl != NULL; curNbl = nextNbl) { nextNbl = curNbl->Next; curNbl->Next = NULL; - + fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); - + // // First check for allowed source if not same source. // @@ -1482,15 +1482,15 @@ Routine Description: { sourcePort = fwdDetail->SourcePortId; sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex; - + sourceNicEntry = MsForwardFindNicByPortIdUnsafe(switchContext, sourcePort, sourceIndex); - + if (sourceNicEntry != NULL && !sourceNicEntry->AllowSends) { RtlInitUnicodeString(&filterReason, L"Blocked by Source MAC Policy"); - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -1500,7 +1500,7 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; @@ -1509,7 +1509,7 @@ Routine Description: sourcePort != switchContext->ExternalPortId) { RtlInitUnicodeString(&filterReason, L"Low Resources"); - + Switch->NdisSwitchHandlers.ReportFilteredNetBufferLists( Switch->NdisSwitchContext, &SxExtensionGuid, @@ -1519,13 +1519,13 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; - } + } } - + // // Ethernet Header is a guaranteed safe access. // @@ -1535,7 +1535,7 @@ Routine Description: LowPagePriority | MdlMappingNoExecute); curHeader = (PMSFORWARD_ETHERNET_HEADER) (curBuffer + (NET_BUFFER_LIST_FIRST_NB(curNbl))->CurrentMdlOffset); - + // // Check for broadcast. (Broadcast if multicast) // @@ -1551,11 +1551,11 @@ Routine Description: sendNbl, SendFlags, 0); - + sendNbl = NULL; nextSendNbl = &sendNbl; } - + if (fwdDetail->NumAvailableDestinations < (switchContext->NumDestinations - 1)) { status = Switch->NdisSwitchHandlers.GrowNetBufferListDestinations( @@ -1563,7 +1563,7 @@ Routine Description: curNbl, (switchContext->NumDestinations - 1 - fwdDetail->NumAvailableDestinations), &broadcastArray); - + if (status != NDIS_STATUS_SUCCESS) { RtlInitUnicodeString(&filterReason, L"Failed to grow destination list."); @@ -1576,7 +1576,7 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; @@ -1589,7 +1589,7 @@ Routine Description: curNbl, &broadcastArray); } - + MsForwardMakeBroadcastArrayUnsafe(switchContext, broadcastArray, sourcePort, @@ -1607,26 +1607,26 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; } - + status = Switch->NdisSwitchHandlers.UpdateNetBufferListDestinations( Switch->NdisSwitchContext, curNbl, (switchContext->NumDestinations - 1), broadcastArray); ASSERT(status == NDIS_STATUS_SUCCESS); - + *nextSendNbl = curNbl; nextSendNbl = &(curNbl->Next); broadcast = TRUE; - + continue; } - + if (RtlEqualMemory(prevMacAddress, curHeader->Destination, @@ -1641,7 +1641,7 @@ Routine Description: curHeader->Destination); // // Not a VM or host, send to external. - // + // if (destinationNicEntry == NULL) { // @@ -1659,12 +1659,12 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; } - + if (sourcePort == switchContext->ExternalPortId) { RtlInitUnicodeString(&filterReason, L"Destination == Source"); @@ -1677,12 +1677,12 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; } - + curDestinationPort = switchContext->ExternalPortId; curDestinationIndex = switchContext->ExternalNicIndex; } @@ -1703,27 +1703,27 @@ Routine Description: 1, curNbl, &filterReason); - + *nextDropNbl = curNbl; nextDropNbl = &curNbl->Next; continue; } } - + RtlMoveMemory(prevMacAddress, curHeader->Destination, sizeof(prevMacAddress)); newDestination.PortId = curDestinationPort; newDestination.NicIndex = curDestinationIndex; newDestination.PreserveVLAN = 0; - + ASSERT(fwdDetail->NumAvailableDestinations > 0); status = Switch->NdisSwitchHandlers.AddNetBufferListDestination( Switch->NdisSwitchContext, curNbl, &newDestination); ASSERT(status == NDIS_STATUS_SUCCESS); - - if(sendNbl != NULL && + + if(sendNbl != NULL && (broadcast || (prevDestinationPort != curDestinationPort || prevDestinationIndex != curDestinationIndex))) @@ -1732,14 +1732,14 @@ Routine Description: sendNbl, SendFlags, 0); - + sendNbl = NULL; nextSendNbl = &sendNbl; } - + *nextSendNbl = curNbl; nextSendNbl = &(curNbl->Next); - + // // Done processing this NBL. // @@ -1747,10 +1747,10 @@ Routine Description: prevDestinationIndex = curDestinationIndex; broadcast = FALSE; } - + Cleanup: NdisReleaseRWLock(switchContext->DispatchLock, &lockState); - + if (sendNbl != NULL) { SxLibSendNetBufferListsIngress(Switch, @@ -1758,7 +1758,7 @@ Cleanup: SendFlags, 0); } - + if (nativeForwardedNbls != NULL) { SxLibSendNetBufferListsIngress(Switch, @@ -1766,7 +1766,7 @@ Cleanup: SendFlags, 0); } - + if (dropNbl != NULL) { SxLibCompleteNetBufferListsIngress(Switch, @@ -1786,14 +1786,14 @@ SxExtStartNetBufferListsEgress( ULONG ReceiveFlags ) /*++ - + Routine Description: No egress processing necessary. - + --*/ { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibSendNetBufferListsEgress(Switch, NetBufferLists, NumberOfNetBufferLists, @@ -1810,14 +1810,14 @@ SxExtStartCompleteNetBufferListsEgress( ULONG ReturnFlags ) /*++ - + Routine Description: No egress processing necessary. - + --*/ { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibCompleteNetBufferListsEgress(Switch, NetBufferLists, ReturnFlags); @@ -1833,14 +1833,14 @@ SxExtStartCompleteNetBufferListsIngress( ULONG SendCompleteFlags ) /*++ - + Routine Description: No ingress complete processing necessary. - + --*/ { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibCompleteNetBufferListsIngress(Switch, NetBufferLists, SendCompleteFlags); @@ -1857,46 +1857,46 @@ MsForwardAddNicUnsafe( _In_ BOOLEAN Connected ) /*++ - + Routine Description: Add given NIC to the NIC list and correlate with MAC policy. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PMSFORWARD_NIC_LIST_ENTRY nicEntry = NULL; PLIST_ENTRY nicList = &SwitchContext->NicList; - + if (NicType == NdisSwitchNicTypeExternal) { goto Cleanup; } - + nicEntry = MsForwardFindNicByPortIdUnsafe(SwitchContext, - PortId, + PortId, NicIndex); - + if (nicEntry == NULL) { nicEntry = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(MSFORWARD_NIC_LIST_ENTRY), SxExtAllocationTag); - + if (nicEntry == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + NdisZeroMemory(nicEntry, sizeof(MSFORWARD_NIC_LIST_ENTRY)); NdisMoveMemory(nicEntry->MacAddress, MacAddress, MSFORWARD_MAC_LENGTH); - + nicEntry->PortId = PortId; nicEntry->NicIndex = NicIndex; nicEntry->NicType = NicType; nicEntry->Connected = Connected; - + if (NicType == NdisSwitchNicTypeInternal) { nicEntry->AllowSends = TRUE; @@ -1905,10 +1905,10 @@ Routine Description: { nicEntry->AllowSends = MsForwardNicHasPolicy(SwitchContext, MacAddress); } - + InsertHeadList(nicList, &nicEntry->ListEntry); } - + Cleanup: return status; } @@ -1921,46 +1921,46 @@ MsForwardAddMacPolicyUnsafe( _In_ PNDIS_SWITCH_OBJECT_INSTANCE_ID PropertyInstanceId ) /*++ - + Routine Description: Add the given policy to the policy list and correlate with the NIC list. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PMSFORWARD_MAC_POLICY_LIST_ENTRY newPolicy; PMSFORWARD_NIC_LIST_ENTRY nic; - + newPolicy = MsForwardFindPolicyByMacAddressUnsafe(SwitchContext, MacPolicyBuffer->MacAddress); - + if (newPolicy == NULL) { newPolicy = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(MSFORWARD_MAC_POLICY_LIST_ENTRY), SxExtAllocationTag); - + if (newPolicy == NULL) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + NdisMoveMemory(&newPolicy->MacAddress, MacPolicyBuffer->MacAddress, sizeof(newPolicy->MacAddress)); - + NdisMoveMemory(&newPolicy->PropertyInstanceId, PropertyInstanceId, sizeof(NDIS_SWITCH_OBJECT_INSTANCE_ID)); - + InsertHeadList(&SwitchContext->PropertyList, &newPolicy->ListEntry); - + nic = MsForwardFindNicByMacAddressUnsafe(SwitchContext, MacPolicyBuffer->MacAddress); - + if (nic != NULL) { nic->AllowSends = TRUE; @@ -1970,7 +1970,7 @@ Routine Description: { status = NDIS_STATUS_DATA_NOT_ACCEPTED; } - + Cleanup: return status; } @@ -1982,30 +1982,30 @@ MsForwardDeleteMacPolicyUnsafe( _In_ PNDIS_SWITCH_OBJECT_INSTANCE_ID PropertyInstanceId ) /*++ - + Routine Description: Delete the given MAC policy, and coorelate with the NIC list. - + --*/ { PMSFORWARD_MAC_POLICY_LIST_ENTRY deletePolicy; PMSFORWARD_NIC_LIST_ENTRY nic; - + deletePolicy = MsForwardFindPolicyByPropertyInstanceIdUnsafe( SwitchContext, PropertyInstanceId); - + if (deletePolicy != NULL) { nic = MsForwardFindNicByMacAddressUnsafe(SwitchContext, deletePolicy->MacAddress); - + if (nic != NULL) { nic->AllowSends = FALSE; } - + RemoveEntryList(&deletePolicy->ListEntry); ExFreePoolWithTag(deletePolicy, SxExtAllocationTag); } @@ -2019,38 +2019,38 @@ MsForwardFindNicByPortIdUnsafe( _In_ NDIS_SWITCH_NIC_INDEX NicIndex ) /*++ - + Routine Description: Search for the NIC needed by port ID. - + --*/ { PLIST_ENTRY nicList = &SwitchContext->NicList; PLIST_ENTRY curEntry = nicList->Flink; PMSFORWARD_NIC_LIST_ENTRY nic = NULL; - + if (IsListEmpty(nicList)) { goto Cleanup; } - + do { nic = CONTAINING_RECORD(curEntry, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + if (nic->PortId == PortId && nic->NicIndex == NicIndex) { goto Cleanup; } - + curEntry = curEntry->Flink; - + } while(curEntry != nicList); - + nic = NULL; - + Cleanup: return nic; } @@ -2062,39 +2062,39 @@ MsForwardFindNicByMacAddressUnsafe( _In_reads_bytes_(6) PUCHAR MacAddress ) /*++ - + Routine Description: Search for the NIC needed by MAC Address. - + --*/ { PLIST_ENTRY nicList = &SwitchContext->NicList; PLIST_ENTRY curEntry = nicList->Flink; PMSFORWARD_NIC_LIST_ENTRY nic = NULL; - + if (IsListEmpty(nicList)) { goto Cleanup; } - + do { nic = CONTAINING_RECORD(curEntry, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + if (RtlEqualMemory(MacAddress, nic->MacAddress, sizeof(nic->MacAddress))) { goto Cleanup; } - + curEntry = curEntry->Flink; - + } while(curEntry != nicList); - + nic = NULL; - + Cleanup: return nic; } @@ -2106,39 +2106,39 @@ MsForwardFindPolicyByMacAddressUnsafe( _In_reads_bytes_(6) PUCHAR MacAddress ) /*++ - + Routine Description: Search for the policy needed by MAC address. - + --*/ { PLIST_ENTRY propertyList = &SwitchContext->PropertyList; PLIST_ENTRY curEntry = propertyList->Flink; PMSFORWARD_MAC_POLICY_LIST_ENTRY policy = NULL; - + if (IsListEmpty(propertyList)) { goto Cleanup; } - + do { policy = CONTAINING_RECORD(curEntry, MSFORWARD_MAC_POLICY_LIST_ENTRY, ListEntry); - + if (RtlEqualMemory(MacAddress, policy->MacAddress, sizeof(policy->MacAddress))) { goto Cleanup; } - + curEntry = curEntry->Flink; - + } while(curEntry != propertyList); - + policy = NULL; - + Cleanup: return policy; } @@ -2150,44 +2150,44 @@ MsForwardFindPolicyByPropertyInstanceIdUnsafe( _In_ PNDIS_SWITCH_OBJECT_INSTANCE_ID PropertyInstanceId ) /*++ - + Routine Description: Search for the policy needed by PropertyInstanceId. - + --*/ { PLIST_ENTRY propertyList = &SwitchContext->PropertyList; PLIST_ENTRY curEntry = propertyList->Flink; PMSFORWARD_MAC_POLICY_LIST_ENTRY policy = NULL; - + if (IsListEmpty(propertyList)) { goto Cleanup; } - + do { policy = CONTAINING_RECORD(curEntry, MSFORWARD_MAC_POLICY_LIST_ENTRY, ListEntry); - + if (RtlEqualMemory(PropertyInstanceId, &policy->PropertyInstanceId, sizeof(policy->PropertyInstanceId))) { goto Cleanup; } - + curEntry = curEntry->Flink; - + } while(curEntry != propertyList); - + policy = NULL; - + Cleanup: return policy; } - + NDIS_STATUS MsForwardDeleteNicUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, @@ -2195,56 +2195,56 @@ MsForwardDeleteNicUnsafe( _In_ NDIS_SWITCH_NIC_INDEX NicIndex ) /*++ - + Routine Description: Remove the NIC represented by the PortId and NicIndex from the NIC list and free its memory. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; - + PMSFORWARD_NIC_LIST_ENTRY nicEntry = MsForwardFindNicByPortIdUnsafe(SwitchContext, PortId, NicIndex); - + if (nicEntry == NULL) { ASSERT(FALSE); goto Cleanup; } - + RemoveEntryList(&nicEntry->ListEntry); ExFreePoolWithTag(nicEntry, SxExtAllocationTag); -Cleanup: +Cleanup: return status; } - - + + VOID MsForwardClearNicListUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext ) /*++ - + Routine Description: Remove all NICs from the list and free all memory. - + --*/ { PMSFORWARD_NIC_LIST_ENTRY nic; PLIST_ENTRY nicList = &SwitchContext->NicList; PLIST_ENTRY headList = NULL; - + while (!IsListEmpty(nicList)) { headList = RemoveHeadList(nicList); - + nic = CONTAINING_RECORD(headList, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + ExFreePoolWithTag(nic, SxExtAllocationTag); } @@ -2257,24 +2257,24 @@ MsForwardClearPropertyListUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext ) /*++ - + Routine Description: Remove all properties from the list and free all memory. - + --*/ { PMSFORWARD_MAC_POLICY_LIST_ENTRY policy; PLIST_ENTRY propertyList = &SwitchContext->PropertyList; PLIST_ENTRY headList = NULL; - + while (!IsListEmpty(propertyList)) { headList = RemoveHeadList(propertyList); - + policy = CONTAINING_RECORD(headList, MSFORWARD_MAC_POLICY_LIST_ENTRY, ListEntry); - + ExFreePoolWithTag(policy, SxExtAllocationTag); } @@ -2288,17 +2288,17 @@ MsForwardNicHasPolicy( _In_reads_bytes_(6) PUCHAR MacAddress ) /*++ - + Routine Description: Returns TRUE if there is a correlated policy to the MAC address given. - + --*/ { return (MsForwardFindPolicyByMacAddressUnsafe(SwitchContext, MacAddress) != NULL); } - + VOID MsForwardMakeBroadcastArrayUnsafe( @@ -2308,11 +2308,11 @@ MsForwardMakeBroadcastArrayUnsafe( _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex ) /*++ - + Routine Description: Creates the destination array of all connected NICs excluding the source given. - + --*/ { PLIST_ENTRY nicList = &SwitchContext->NicList; @@ -2320,17 +2320,17 @@ Routine Description: PMSFORWARD_NIC_LIST_ENTRY nic = NULL; UINT32 index = BroadcastArray->NumDestinations; PNDIS_SWITCH_PORT_DESTINATION destination; - + if (IsListEmpty(nicList)) { goto Cleanup; } - + do { nic = CONTAINING_RECORD(curEntry, MSFORWARD_NIC_LIST_ENTRY, ListEntry); - + if ((SourcePortId == nic->PortId && SourceNicIndex == nic->NicIndex) || !nic->Connected) @@ -2345,18 +2345,18 @@ Routine Description: continue; } } - + destination = NDIS_SWITCH_PORT_DESTINATION_AT_ARRAY_INDEX(BroadcastArray, index); NdisZeroMemory(destination, sizeof(NDIS_SWITCH_PORT_DESTINATION)); - + destination->PortId = nic->PortId; destination->NicIndex = nic->NicIndex; - + ++index; curEntry = curEntry->Flink; - + } while(curEntry != nicList); - + if (SourcePortId != SwitchContext->ExternalPortId && SwitchContext->ExternalNicConnected) { @@ -2364,7 +2364,7 @@ Routine Description: destination->PortId = SwitchContext->ExternalPortId; destination->NicIndex = SwitchContext->ExternalNicIndex; } - + Cleanup: return; } @@ -2376,10 +2376,10 @@ MsForwardInitSwitch( _In_ PMSFORWARD_CONTEXT SwitchContext ) /*++ - + Routine Description: Initializes the switch state. - + --*/ { NDIS_STATUS status = NDIS_STATUS_SUCCESS; @@ -2393,7 +2393,7 @@ Routine Description: PNDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS portPropertyParameters = NULL; PNDIS_SWITCH_PORT_PROPERTY_ENUM_INFO portPropertyInfo = NULL; PNDIS_SWITCH_PORT_PROPERTY_VLAN vlanProperty; - + ASSERT(!SwitchContext->IsActive); // @@ -2403,25 +2403,25 @@ Routine Description: NdisSwitchPropertyTypeCustom, (PNDIS_SWITCH_OBJECT_ID)&MacAddressPolicyGuid, &switchPropertyParameters); - + if (status != NDIS_STATUS_SUCCESS) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + switchPropertyInfo = NDIS_SWITCH_PROPERTY_ENUM_PARAMETERS_GET_FIRST_INFO(switchPropertyParameters); - + for (arrIndex = 0; arrIndex < switchPropertyParameters->NumProperties; ++arrIndex) { // - // Should always get back v1 or later. It is safe to access the + // Should always get back v1 or later. It is safe to access the // v1 version of the structure if newer property is retrieved. // - ASSERT(switchPropertyInfo->PropertyVersion >= + ASSERT(switchPropertyInfo->PropertyVersion >= MAC_ADDRESS_POLICY_VERSION); customPropertyInfo = @@ -2433,35 +2433,35 @@ Routine Description: status = MsForwardAddMacPolicyUnsafe(SwitchContext, macAddressPolicy, &switchPropertyInfo->PropertyInstanceId); - + if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } - + switchPropertyInfo = NDIS_SWITCH_PROPERTY_ENUM_INFO_GET_NEXT(switchPropertyInfo); } // // Now, get NIC list. - // + // status = SxLibGetNicArrayUnsafe(Switch, &nicArray); if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } - + for (arrIndex = 0; arrIndex < nicArray->NumElements; ++arrIndex) { curNic = NDIS_SWITCH_NIC_AT_ARRAY_INDEX(nicArray, arrIndex); - + status = Switch->NdisSwitchHandlers.ReferenceSwitchPort( Switch->NdisSwitchContext, curNic->PortId); - + ASSERT(status == NDIS_STATUS_SUCCESS); - + // // Get VLAN Port property to ensure no VLAN set. // @@ -2470,26 +2470,26 @@ Routine Description: NdisSwitchPortPropertyTypeVlan, NULL, &portPropertyParameters); - + if (status != NDIS_STATUS_SUCCESS) { status = NDIS_STATUS_RESOURCES; goto Cleanup; } - + portPropertyInfo = NDIS_SWITCH_PORT_PROPERTY_ENUM_PARAMETERS_GET_FIRST_INFO(portPropertyParameters); // - // Should always get back v1 or later. It is safe to access the v1 + // Should always get back v1 or later. It is safe to access the v1 // version of the structure if newer property is retrieved. // - ASSERT(portPropertyInfo->PropertyVersion >= + ASSERT(portPropertyInfo->PropertyVersion >= NDIS_SWITCH_PORT_PROPERTY_VLAN_REVISION_1); vlanProperty = NDIS_SWITCH_PORT_PROPERTY_ENUM_INFO_GET_PROPERTY(portPropertyInfo); - + // // Real production code should support VLAN, // and not fail SxExtRestartSwitch. @@ -2500,13 +2500,13 @@ Routine Description: status = NDIS_STATUS_FAILURE; goto Cleanup; } - + status = Switch->NdisSwitchHandlers.DereferenceSwitchPort( Switch->NdisSwitchContext, curNic->PortId); - + ASSERT(status == NDIS_STATUS_SUCCESS); - + // // If a VF is assigned to a NIC, then the traffic // flows through the VF and not the switch. This means @@ -2518,36 +2518,36 @@ Routine Description: Switch->NdisSwitchContext, curNic->PortId, curNic->NicIndex); - + ASSERT(status == NDIS_STATUS_SUCCESS); - + SxLibRevokeVfUnsafe(Switch, curNic->PortId); - + status = Switch->NdisSwitchHandlers.DereferenceSwitchNic( Switch->NdisSwitchContext, curNic->PortId, curNic->NicIndex); - + ASSERT(status == NDIS_STATUS_SUCCESS); } - + // // Now we've verified we can support the NIC, so // check if there's a property for it, and add it to // the NIC list. - // + // status = MsForwardAddNicUnsafe(SwitchContext, curNic->PermanentMacAddress, curNic->PortId, curNic->NicIndex, curNic->NicType, (curNic->NicState == NdisSwitchNicStateConnected)); - + if (status != NDIS_STATUS_SUCCESS) { goto Cleanup; } - + if (curNic->NicType == NdisSwitchNicTypeExternal && curNic->NicIndex != 0 && SwitchContext->ExternalPortId == 0) @@ -2562,7 +2562,7 @@ Routine Description: ++(SwitchContext->NumDestinations); } } - + SwitchContext->IsActive = TRUE; Cleanup: @@ -2570,17 +2570,17 @@ Cleanup: { ExFreePoolWithTag(switchPropertyParameters, SxExtAllocationTag); } - + if (portPropertyParameters != NULL) { ExFreePoolWithTag(portPropertyParameters, SxExtAllocationTag); } - + if (nicArray != NULL) { ExFreePoolWithTag(nicArray, SxExtAllocationTag); } - + return status; } diff --git a/network/ndis/extension/samples/forward/MsForwardExt.h b/network/ndis/extension/samples/forward/MsForwardExt.h index ed6ac629..5884fa7a 100644 --- a/network/ndis/extension/samples/forward/MsForwardExt.h +++ b/network/ndis/extension/samples/forward/MsForwardExt.h @@ -28,7 +28,7 @@ typedef struct _MSFORWARD_CONTEXT NDIS_SWITCH_PORT_ID ExternalPortId; NDIS_SWITCH_NIC_INDEX ExternalNicIndex; BOOLEAN ExternalNicConnected; - + // // This sample uses linked lists for the NICs and property // lookup. THIS IS NOT RECOMMENDED. @@ -36,7 +36,7 @@ typedef struct _MSFORWARD_CONTEXT LIST_ENTRY NicList; LIST_ENTRY PropertyList; PNDIS_RW_LOCK_EX DispatchLock; - + UINT32 NumDestinations; BOOLEAN IsInitialRestart; } MSFORWARD_CONTEXT, *PMSFORWARD_CONTEXT; @@ -119,7 +119,7 @@ extern const NDIS_SWITCH_OBJECT_ID MacAddressPolicyStatusGuid; // // Switch Property Macros -// +// #define MAC_ADDRESS_POLICY_VERSION 0x0100 #define MAC_ADDRESS_POLICY_SERIALIZATION_VERSION NDIS_SWITCH_OBJECT_SERIALIZATION_VERSION_1 @@ -142,26 +142,26 @@ MsForwardAddNicUnsafe( _In_ NDIS_SWITCH_NIC_TYPE NicType, _In_ BOOLEAN Connected ); - + NDIS_STATUS MsForwardDeleteNicUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, _In_ NDIS_SWITCH_PORT_ID PortId, _In_ NDIS_SWITCH_NIC_INDEX NicIndex ); - + VOID MsForwardClearNicListUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext ); - + PMSFORWARD_NIC_LIST_ENTRY MsForwardFindNicByPortIdUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, _In_ NDIS_SWITCH_PORT_ID PortId, _In_ NDIS_SWITCH_NIC_INDEX NicIndex ); - + PMSFORWARD_NIC_LIST_ENTRY MsForwardFindNicByMacAddressUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, @@ -174,7 +174,7 @@ MsForwardAddMacPolicyUnsafe( _In_ PMSFORWARD_MAC_ADDRESS_POLICY MacPolicyBuffer, _In_ PNDIS_SWITCH_OBJECT_INSTANCE_ID PropertyInstanceId ); - + VOID MsForwardDeleteMacPolicyUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, @@ -185,25 +185,25 @@ VOID MsForwardClearPropertyListUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext ); - + PMSFORWARD_MAC_POLICY_LIST_ENTRY MsForwardFindPolicyByMacAddressUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, _In_reads_bytes_(6) PUCHAR MacAddress ); - + PMSFORWARD_MAC_POLICY_LIST_ENTRY MsForwardFindPolicyByPropertyInstanceIdUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, _In_ PNDIS_SWITCH_OBJECT_INSTANCE_ID PropertyInstanceId ); - + BOOLEAN MsForwardNicHasPolicy( _In_ PMSFORWARD_CONTEXT SwitchContext, _In_reads_bytes_(6) PUCHAR MacAddress ); - + VOID MsForwardMakeBroadcastArrayUnsafe( _In_ PMSFORWARD_CONTEXT SwitchContext, @@ -211,7 +211,7 @@ MsForwardMakeBroadcastArrayUnsafe( _In_ NDIS_SWITCH_PORT_ID SourcePortId, _In_ NDIS_SWITCH_NIC_INDEX SourceNicIndex ); - + NDIS_STATUS MsForwardInitSwitch( _In_ PSX_SWITCH_OBJECT Switch, diff --git a/network/ndis/extension/samples/forward/setRoute.ps1 b/network/ndis/extension/samples/forward/setRoute.ps1 index 71899087..bfb21f8d 100644 --- a/network/ndis/extension/samples/forward/setRoute.ps1 +++ b/network/ndis/extension/samples/forward/setRoute.ps1 @@ -10,7 +10,7 @@ function StringToMacAddress([String]$MacString) $macArray = @(); $byteOne = 0; $byteTwo = 0; - + for($i = 0; $i -lt 6; $i++) { $byteChars = $MacString.ToCharArray(2*$i, 2); @@ -44,7 +44,7 @@ foreach($vm in $vmArr) { $vmName = $vm.Name $adapters = Get-VmNetworkAdapter -VmName $vmName - + foreach($adapter in $adapters) { Write-Host "Setting Policy for $vmName..." diff --git a/network/ndis/extension/samples/passthrough/MsPassthroughExt.c b/network/ndis/extension/samples/passthrough/MsPassthroughExt.c index e99eeac5..1bf50f09 100644 --- a/network/ndis/extension/samples/passthrough/MsPassthroughExt.c +++ b/network/ndis/extension/samples/passthrough/MsPassthroughExt.c @@ -47,7 +47,7 @@ SxExtCreateSwitch( ) { UNREFERENCED_PARAMETER(Switch); - + *ExtensionContext = NULL; return NDIS_STATUS_SUCCESS; } @@ -62,7 +62,7 @@ SxExtDeleteSwitch( { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + return; } @@ -76,7 +76,7 @@ SxExtActivateSwitch( { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + return; } @@ -95,7 +95,7 @@ SxExtRestartSwitch( } -_Use_decl_annotations_ +_Use_decl_annotations_ VOID SxExtPauseSwitch( PSX_SWITCH_OBJECT Switch, @@ -104,7 +104,7 @@ SxExtPauseSwitch( { UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); - + return; } @@ -120,7 +120,7 @@ SxExtCreatePort( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return NDIS_STATUS_SUCCESS; } @@ -136,7 +136,7 @@ SxExtUpdatePort( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return; } @@ -152,7 +152,7 @@ SxExtCreateNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return NDIS_STATUS_SUCCESS; } @@ -168,7 +168,7 @@ SxExtConnectNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return; } @@ -184,7 +184,7 @@ SxExtUpdateNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return; } @@ -200,7 +200,7 @@ SxExtDisconnectNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return; } @@ -216,7 +216,7 @@ SxExtDeleteNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Nic); - + return; } @@ -232,14 +232,14 @@ SxExtTeardownPort( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return; } _Use_decl_annotations_ VOID -SxExtDeletePort( +SxExtDeletePort( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_PORT_PARAMETERS Port @@ -248,14 +248,14 @@ SxExtDeletePort( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(Port); - + return; } _Use_decl_annotations_ NDIS_STATUS -SxExtSaveNic( +SxExtSaveNic( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState, @@ -266,7 +266,7 @@ SxExtSaveNic( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + *BytesWritten = 0; *BytesNeeded = 0; return NDIS_STATUS_SUCCESS; @@ -275,7 +275,7 @@ SxExtSaveNic( _Use_decl_annotations_ VOID -SxExtSaveNicComplete( +SxExtSaveNicComplete( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState @@ -284,14 +284,14 @@ SxExtSaveNicComplete( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + return; } -_Use_decl_annotations_ +_Use_decl_annotations_ NDIS_STATUS -SxExtNicRestore( +SxExtNicRestore( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState, @@ -301,7 +301,7 @@ SxExtNicRestore( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + *BytesRestored = 0; return NDIS_STATUS_SUCCESS; } @@ -309,7 +309,7 @@ SxExtNicRestore( _Use_decl_annotations_ VOID -SxExtNicRestoreComplete( +SxExtNicRestoreComplete( PSX_SWITCH_OBJECT Switch, NDIS_HANDLE ExtensionContext, PNDIS_SWITCH_NIC_SAVE_STATE SaveState @@ -318,7 +318,7 @@ SxExtNicRestoreComplete( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SaveState); - + return; } @@ -334,7 +334,7 @@ SxExtAddSwitchProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SwitchProperty); - + return NDIS_STATUS_NOT_SUPPORTED; } @@ -350,7 +350,7 @@ SxExtUpdateSwitchProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SwitchProperty); - + return NDIS_STATUS_NOT_SUPPORTED; } @@ -366,7 +366,7 @@ SxExtDeleteSwitchProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SwitchProperty); - + return FALSE; } @@ -382,7 +382,7 @@ SxExtAddPortProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(PortProperty); - + return NDIS_STATUS_NOT_SUPPORTED; } @@ -398,7 +398,7 @@ SxExtUpdatePortProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(PortProperty); - + return NDIS_STATUS_NOT_SUPPORTED; } @@ -414,7 +414,7 @@ SxExtDeletePortProperty( UNREFERENCED_PARAMETER(Switch); UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(PortProperty); - + return FALSE; } @@ -432,7 +432,7 @@ SxExtQuerySwitchFeatureStatus( UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(SwitchFeatureStatus); UNREFERENCED_PARAMETER(BytesNeeded); - + return FALSE; } @@ -450,10 +450,10 @@ SxExtQueryPortFeatureStatus( UNREFERENCED_PARAMETER(ExtensionContext); UNREFERENCED_PARAMETER(PortFeatureStatus); UNREFERENCED_PARAMETER(BytesNeeded); - + return FALSE; } - + _Use_decl_annotations_ NDIS_STATUS @@ -474,7 +474,7 @@ SxExtProcessNicRequest( UNREFERENCED_PARAMETER(SourceNicIndex); UNREFERENCED_PARAMETER(DestinationPortId); UNREFERENCED_PARAMETER(DestinationNicIndex); - + return NDIS_STATUS_SUCCESS; } @@ -500,10 +500,10 @@ SxExtProcessNicRequestComplete( UNREFERENCED_PARAMETER(DestinationPortId); UNREFERENCED_PARAMETER(DestinationNicIndex); UNREFERENCED_PARAMETER(Status); - + return NDIS_STATUS_SUCCESS; } - + _Use_decl_annotations_ NDIS_STATUS @@ -520,7 +520,7 @@ SxExtProcessNicStatus( UNREFERENCED_PARAMETER(StatusIndication); UNREFERENCED_PARAMETER(SourcePortId); UNREFERENCED_PARAMETER(SourceNicIndex); - + return NDIS_STATUS_SUCCESS; } @@ -535,7 +535,7 @@ SxExtStartNetBufferListsIngress( ) { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibSendNetBufferListsIngress(Switch, NetBufferLists, SendFlags, @@ -543,7 +543,7 @@ SxExtStartNetBufferListsIngress( } -_Use_decl_annotations_ +_Use_decl_annotations_ VOID SxExtStartNetBufferListsEgress( PSX_SWITCH_OBJECT Switch, @@ -554,7 +554,7 @@ SxExtStartNetBufferListsEgress( ) { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibSendNetBufferListsEgress(Switch, NetBufferLists, NumberOfNetBufferLists, @@ -572,7 +572,7 @@ SxExtStartCompleteNetBufferListsEgress( ) { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibCompleteNetBufferListsEgress(Switch, NetBufferLists, ReturnFlags); @@ -589,9 +589,9 @@ SxExtStartCompleteNetBufferListsIngress( ) { UNREFERENCED_PARAMETER(ExtensionContext); - + SxLibCompleteNetBufferListsIngress(Switch, NetBufferLists, SendCompleteFlags); } - + diff --git a/network/ndis/filter/filter.c b/network/ndis/filter/filter.c index 7145b887..2ccda62a 100644 --- a/network/ndis/filter/filter.c +++ b/network/ndis/filter/filter.c @@ -108,7 +108,7 @@ Return Value: // // TODO: Most handlers are optional, however, this sample includes them - // all for illustrative purposes. If you do not need a particular + // all for illustrative purposes. If you do not need a particular // handler, set it to NULL and NDIS will more efficiently pass the // operation through on your behalf. // @@ -250,7 +250,7 @@ Return Value: NDIS_STATUS_FAILURE: FilterAttach could not set up this instance of this filter and it has called NdisWriteErrorLogEntry with parameters specifying the reason for failure. -N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper +N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper layer can send Irps to the filter. --*/ @@ -275,7 +275,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper // Verify the media type is supported. This is a last resort; the // the filter should never have been bound to an unsupported miniport // to begin with. If this driver is marked as a Mandatory filter (which - // is the default for this sample; see the INF file), failing to attach + // is the default for this sample; see the INF file), failing to attach // here will leave the network adapter in an unusable state. // // Your setup/install code should not bind the filter to unsupported @@ -401,10 +401,10 @@ Return Value: NDIS_STATUS_SUCCESS if filter pauses successfully, NDIS_STATUS_PENDING if not. No other return value is allowed (pause must succeed, eventually). -N.B.: When the filter is in Pausing state, it can still process OID requests, +N.B.: When the filter is in Pausing state, it can still process OID requests, complete sending, and returning packets to NDIS, and also indicate status. - After this function completes, the filter must not attempt to send or - receive packets, but it may still process OID requests and status + After this function completes, the filter must not attempt to send or + receive packets, but it may still process OID requests and status indications. --*/ @@ -429,7 +429,7 @@ N.B.: When the filter is in Pausing state, it can still process OID requests, // // Do whatever work is required to bring the filter into the Paused state. // - // If you have diverted and queued any send or receive NBLs, return them + // If you have diverted and queued any send or receive NBLs, return them // now. // // If you send or receive original NBLs, stop doing that and wait for your @@ -498,7 +498,7 @@ Return Value: #if 0 // - // The code is here just to demonstrate how to call NDIS to write an + // The code is here just to demonstrate how to call NDIS to write an // event to the eventlog. // PWCHAR ErrorString = L"Ndislwf"; @@ -518,7 +518,7 @@ Return Value: // // This sample doesn't actually do anything with the configuration handle; // it is opened here for illustrative purposes. If you do not need to - // read configuration, you may omit the code manipulating the + // read configuration, you may omit the code manipulating the // ConfigurationHandle. // @@ -530,9 +530,9 @@ Return Value: NdisRestartAttributes = RestartParameters->RestartAttributes; // - // If NdisRestartAttributes is not NULL, then the filter can modify generic - // attributes and add new media specific info attributes at the end. - // Otherwise, if NdisRestartAttributes is NULL, the filter should not try to + // If NdisRestartAttributes is not NULL, then the filter can modify generic + // attributes and add new media specific info attributes at the end. + // Otherwise, if NdisRestartAttributes is NULL, the filter should not try to // modify/add attributes. // if (NdisRestartAttributes != NULL) @@ -777,7 +777,7 @@ NOTE: Called at <= DISPATCH_LEVEL (unlike a miniport's MiniportOidRequest) // // If your filter driver does not need to modify any OID requests, then // you may simply omit this routine entirely; NDIS will pass OID requests - // down on your behalf. This is more efficient than implementing a + // down on your behalf. This is more efficient than implementing a // routine that does nothing but clone all requests, as in the sample here. // @@ -864,8 +864,8 @@ Routine Description: If your filter driver does not intercept and hold onto any OID requests, then you do not need to implement this routine. You may simply omit it. Furthermore, if the filter only holds onto OID requests so it can pass - down a clone (the most common case) the filter does not need to implement - this routine; NDIS will then automatically request that the lower-level + down a clone (the most common case) the filter does not need to implement + this routine; NDIS will then automatically request that the lower-level filter/miniport cancel your cloned OID. Most filters do not need to implement this routine. @@ -1021,7 +1021,7 @@ Arguments: NOTE: called at <= DISPATCH_LEVEL - FILTER driver may call NdisFIndicateStatus to generate a status indication to + FILTER driver may call NdisFIndicateStatus to generate a status indication to all higher layer modules. --*/ @@ -1037,8 +1037,8 @@ NOTE: called at <= DISPATCH_LEVEL // // The filter may do processing on the status indication here, including // intercepting and dropping it entirely. However, the sample does nothing - // with status indications except pass them up to the higher layer. It is - // more efficient to omit the FilterStatus handler entirely if it does + // with status indications except pass them up to the higher layer. It is + // more efficient to omit the FilterStatus handler entirely if it does // nothing, but it is included in this sample for illustrative purposes. // @@ -1154,7 +1154,7 @@ NOTE: called at PASSIVE_LEVEL NDIS_STATUS Status = NDIS_STATUS_SUCCESS; // - // The filter may do processing on the event here, including intercepting + // The filter may do processing on the event here, including intercepting // and dropping it entirely. However, the sample does nothing with Net PNP // events, except pass them up to the next higher layer. It is more // efficient to omit the FilterNetPnPEvent handler entirely if it does @@ -1179,10 +1179,10 @@ Routine Description: Send complete handler - This routine is invoked whenever the lower layer is finished processing + This routine is invoked whenever the lower layer is finished processing sent NET_BUFFER_LISTs. If the filter does not need to be involved in the send path, you should remove this routine and the FilterSendNetBufferLists - routine. NDIS will pass along send packets on behalf of your filter more + routine. NDIS will pass along send packets on behalf of your filter more efficiently than the filter can. Arguments: @@ -1260,7 +1260,7 @@ Routine Description: This function is an optional function for filter drivers. If provided, NDIS will call this function to transmit a linked list of NetBuffers, described by a NetBufferList, over the network. If this handler is NULL, NDIS will skip calling - this filter when sending a NetBufferList and will call the next lower + this filter when sending a NetBufferList and will call the next lower driver in the stack. A filter that doesn't provide a FilerSendNetBufferList handler can not originate a send on its own. @@ -1324,7 +1324,7 @@ Arguments: } FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel); } - + // // If necessary, queue the NetBufferLists in a local structure for later // processing. However, do not queue them for "too long", or else the @@ -1332,7 +1332,7 @@ Arguments: // NBL for an unbounded amount of time, then allocate memory, perform a // deep copy, and complete the original NBL. // - + NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags); @@ -1365,8 +1365,8 @@ Routine Description: Arguments: FilterInstanceContext - our filter context area - NetBufferLists - a linked list of NetBufferLists that this - filter driver indicated in a previous call to + NetBufferLists - a linked list of NetBufferLists that this + filter driver indicated in a previous call to NdisFIndicateReceiveNetBufferLists ReturnFlags - flags specifying if the caller is at DISPATCH_LEVEL @@ -1383,7 +1383,7 @@ Arguments: // // If your filter injected any receive packets into the datapath to be - // received, you must identify their NBLs here and remove them from the + // received, you must identify their NBLs here and remove them from the // chain. Do not attempt to receive-return your NBLs down to the lower // layer. // @@ -1405,7 +1405,7 @@ Arguments: } } - + // Return the received NBLs. If you removed any NBLs from the chain, make // sure the chain isn't empty (i.e., NetBufferLists!=NULL). @@ -1449,7 +1449,7 @@ Routine Description: filter when processing a receive indication and will call the next higher driver in the stack. A filter that doesn't provide a FilterReceiveNetBufferLists handler cannot provide a - FilterReturnNetBufferLists handler and cannot a initiate an original receive + FilterReturnNetBufferLists handler and cannot a initiate an original receive indication on its own. Arguments: @@ -1460,7 +1460,7 @@ Arguments: ReceiveFlags - N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND. - This controls whether the receive indication is an synchronous or + This controls whether the receive indication is an synchronous or asynchronous function call. --*/ @@ -1509,7 +1509,7 @@ N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND // // if NDIS_TEST_RECEIVE_CANNOT_PEND(ReceiveFlags): // For each NBL that is NOT dropped, temporarily unlink it from - // the linked list, and indicate it up alone with + // the linked list, and indicate it up alone with // NdisFIndicateReceiveNetBufferLists and the // NDIS_RECEIVE_FLAGS_RESOURCES flag set. Then immediately // relink the NBL back into the chain. When all NBLs have been @@ -1520,8 +1520,8 @@ N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND // Return the first chain with NdisFReturnNetBufferLists, and // indicate up the rest with NdisFIndicateReceiveNetBufferLists. // - // Note: on the receive path for Ethernet packets, one NBL will have - // exactly one NB. So (assuming you are receiving on Ethernet, or are + // Note: on the receive path for Ethernet packets, one NBL will have + // exactly one NB. So (assuming you are receiving on Ethernet, or are // attached above Native WiFi) you do not need to worry about dropping // one NB, but trying to indicate up the remaining NBs on the same NBL. // In other words, if the first NB should be dropped, drop the whole NBL. @@ -1589,7 +1589,7 @@ Routine Description: This function cancels any NET_BUFFER_LISTs pended in the filter and then calls the NdisFCancelSendNetBufferLists to propagate the cancel operation. - If your driver does not queue any send NBLs, you may omit this routine. + If your driver does not queue any send NBLs, you may omit this routine. NDIS will propagate the cancelation on your behalf more efficiently. Arguments: diff --git a/network/ndis/filter/filteruser.h b/network/ndis/filter/filteruser.h index ac03e04b..ba09a860 100644 --- a/network/ndis/filter/filteruser.h +++ b/network/ndis/filter/filteruser.h @@ -1,5 +1,5 @@ // -// Copyright (C) Microsoft. All rights reserved. +// Copyright (C) Microsoft Corporation. All rights reserved. // #ifndef __FILTERUSER_H__ #define __FILTERUSER_H__ diff --git a/network/ndis/filter/flt_dbg.c b/network/ndis/filter/flt_dbg.c index 1d52071d..a65c4312 100644 --- a/network/ndis/filter/flt_dbg.c +++ b/network/ndis/filter/flt_dbg.c @@ -4,7 +4,7 @@ Copyright (c) 2001 Microsoft Corporation Module Name: - debug.c + flt_dbg.c Abstract: diff --git a/network/ndis/filter/flt_dbg.h b/network/ndis/filter/flt_dbg.h index f3513588..a7cb0da3 100644 --- a/network/ndis/filter/flt_dbg.h +++ b/network/ndis/filter/flt_dbg.h @@ -4,7 +4,7 @@ Copyright (c) 2001 Microsoft Corporation Module Name: - debug.h + flt_dbg.h Abstract: @@ -17,9 +17,6 @@ Notes: --*/ -// disable warnings - - #ifndef _FILTDEBUG__H #define _FILTDEBUG__H diff --git a/network/ndis/mux/driver/60/miniport.c b/network/ndis/mux/driver/60/miniport.c index f30c4b62..627218c7 100644 --- a/network/ndis/mux/driver/60/miniport.c +++ b/network/ndis/mux/driver/60/miniport.c @@ -79,7 +79,7 @@ NDIS_OID VElanSupportedOids[] = OID_PNP_REMOVE_WAKE_UP_PATTERN, #if IEEE_VLAN_SUPPORT OID_GEN_VLAN_ID, -#endif +#endif OID_PNP_ENABLE_WAKE_UP }; @@ -121,8 +121,8 @@ Return Value: NET_IFINDEX HigherLayerIfIndex, LowerLayerIfIndex; NDIS_MINIPORT_ADAPTER_ATTRIBUTES MiniportAttributesContent; const PNDIS_MINIPORT_ADAPTER_ATTRIBUTES MiniportAttributes = &MiniportAttributesContent; - - + + #if IEEE_VLAN_SUPPORT NDIS_STRING strVlanId = NDIS_STRING_CONST("VlanID"); @@ -136,9 +136,9 @@ Return Value: UNREFERENCED_PARAMETER(MiniportDriverContext); - + // - // Start off by retrieving our virtual miniport context (VELAN) and + // Start off by retrieving our virtual miniport context (VELAN) and // storing the Miniport handle in it. // @@ -179,20 +179,20 @@ Return Value: MiniportAttributesContent.RegistrationAttributes.CheckForHangTimeInSeconds = 0; MiniportAttributesContent.RegistrationAttributes.InterfaceType = 0; - - + + NDIS_DECLARE_MINIPORT_ADAPTER_CONTEXT(VELAN); Status = NdisMSetMiniportAttributes(MiniportAdapterHandle, MiniportAttributes); - + if (Status != NDIS_STATUS_SUCCESS) { break; } - + // // Access configuration parameters for this miniport. @@ -220,14 +220,14 @@ Return Value: ConfigurationHandle); // - // If there is a NetworkAddress override, use it + // If there is a NetworkAddress override, use it // - if (((Status == NDIS_STATUS_SUCCESS) + if (((Status == NDIS_STATUS_SUCCESS) && (i == ETH_LENGTH_OF_ADDRESS)) - && ((!ETH_IS_MULTICAST(NetworkAddress)) + && ((!ETH_IS_MULTICAST(NetworkAddress)) && (ETH_IS_LOCALLY_ADMINISTERED (NetworkAddress)))) { - + ETH_COPY_NETWORK_ADDRESS( pVElan->CurrentAddress, NetworkAddress); @@ -241,7 +241,7 @@ Return Value: // ignore error reading the network address // Status = NDIS_STATUS_SUCCESS; - + #if IEEE_VLAN_SUPPORT // // Read VLAN ID @@ -269,11 +269,11 @@ Return Value: else { - + pVElan->VlanId = VLANID_DEFAULT; Status = NDIS_STATUS_SUCCESS; } -#endif +#endif NdisCloseConfiguration(ConfigurationHandle); @@ -286,7 +286,7 @@ Return Value: MiniportAttributesContent.GeneralAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES; MiniportAttributesContent.GeneralAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1; - MiniportAttributesContent.GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); + MiniportAttributesContent.GeneralAttributes.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES); MiniportAttributesContent.GeneralAttributes.MediaType = VELAN_MEDIA_TYPE; MiniportAttributesContent.GeneralAttributes.MtuSize = pVElan->pAdapt->BindParameters.MtuSize; @@ -294,10 +294,10 @@ Return Value: MiniportAttributesContent.GeneralAttributes.MaxRcvLinkSpeed = pVElan->pAdapt->BindParameters.MaxRcvLinkSpeed; MiniportAttributesContent.GeneralAttributes.XmitLinkSpeed = pVElan->pAdapt->BindParameters.XmitLinkSpeed; MiniportAttributesContent.GeneralAttributes.RcvLinkSpeed = pVElan->pAdapt->BindParameters.RcvLinkSpeed; - + MUX_ACQUIRE_ADAPT_READ_LOCK(pVElan->pAdapt, &LockState); - + // // Miniport below has indicated some status indication // @@ -305,21 +305,21 @@ Return Value: MiniportAttributesContent.GeneralAttributes.MediaDuplexState = pVElan->pAdapt->LastIndicatedLinkState.MediaDuplexState; MiniportAttributesContent.GeneralAttributes.XmitLinkSpeed = pVElan->pAdapt->LastIndicatedLinkState.XmitLinkSpeed; MiniportAttributesContent.GeneralAttributes.RcvLinkSpeed = pVElan->pAdapt->LastIndicatedLinkState.RcvLinkSpeed; - + pVElan->LastIndicatedStatus = NDIS_STATUS_LINK_STATE; pVElan->LastIndicatedLinkState = pVElan->pAdapt->LastIndicatedLinkState; - + MiniportAttributesContent.GeneralAttributes.LookaheadSize = pVElan->pAdapt->BindParameters.LookaheadSize; MiniportAttributesContent.GeneralAttributes.MaxMulticastListSize = pVElan->pAdapt->BindParameters.MaxMulticastListSize; MiniportAttributesContent.GeneralAttributes.MacAddressLength = pVElan->pAdapt->BindParameters.MacAddressLength; - + MiniportAttributesContent.GeneralAttributes.PhysicalMediumType = pVElan->pAdapt->BindParameters.PhysicalMediumType ; - MiniportAttributesContent.GeneralAttributes.AccessType = pVElan->pAdapt->BindParameters.AccessType ; - MiniportAttributesContent.GeneralAttributes.DirectionType = pVElan->pAdapt->BindParameters.DirectionType; - MiniportAttributesContent.GeneralAttributes.ConnectionType = pVElan->pAdapt->BindParameters.ConnectionType ; - MiniportAttributesContent.GeneralAttributes.IfType = pVElan->pAdapt->BindParameters.IfType ; + MiniportAttributesContent.GeneralAttributes.AccessType = pVElan->pAdapt->BindParameters.AccessType ; + MiniportAttributesContent.GeneralAttributes.DirectionType = pVElan->pAdapt->BindParameters.DirectionType; + MiniportAttributesContent.GeneralAttributes.ConnectionType = pVElan->pAdapt->BindParameters.ConnectionType ; + MiniportAttributesContent.GeneralAttributes.IfType = pVElan->pAdapt->BindParameters.IfType ; MiniportAttributesContent.GeneralAttributes.IfConnectorPresent = FALSE; // RFC 2665 TRUE if physical adapter if (pVElan->pAdapt->BindParameters.RcvScaleCapabilities) @@ -330,7 +330,7 @@ Return Value: { MiniportAttributesContent.GeneralAttributes.RecvScaleCapabilities = NULL; } - + MiniportAttributesContent.GeneralAttributes.MacOptions = NDIS_MAC_OPTION_NO_LOOPBACK; @@ -339,7 +339,7 @@ Return Value: NDIS_MAC_OPTION_8021Q_VLAN); #endif - + MiniportAttributesContent.GeneralAttributes.SupportedPacketFilters = pVElan->pAdapt->BindParameters.SupportedPacketFilters; MiniportAttributesContent.GeneralAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED | @@ -351,7 +351,7 @@ Return Value: NDIS_STATISTICS_TRANSMIT_QUEUE_LENGTH_SUPPORTED | NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED; - + NdisMoveMemory(&MiniportAttributesContent.GeneralAttributes.CurrentMacAddress, &pVElan->CurrentAddress, ETH_LENGTH_OF_ADDRESS); @@ -369,7 +369,7 @@ Return Value: pVElan->MiniportInitPending = FALSE; } while (FALSE); - + // // If we had received an UnbindAdapter notification on the underlying // adapter, we would have blocked that thread waiting for the IM Init @@ -391,13 +391,13 @@ Return Value: // HigherLayerIfIndex = MiniportInitParameters->IfIndex; LowerLayerIfIndex = pVElan->pAdapt->BindParameters.BoundIfIndex; - + Status = NdisIfAddIfStackEntry(HigherLayerIfIndex, LowerLayerIfIndex); if (Status == NDIS_STATUS_SUCCESS) { - pVElan->IfIndex = HigherLayerIfIndex; + pVElan->IfIndex = HigherLayerIfIndex; } // @@ -407,7 +407,7 @@ Return Value: } else - { + { pVElan->MiniportAdapterHandle = NULL; } @@ -415,9 +415,9 @@ Return Value: { pVElan->MiniportInitPending = FALSE; } - + // TODO: check to see if we can set the init event in a failure case? - + NdisSetEvent(&pVElan->MiniportInitEvent); DBGPRINT(MUX_LOUD, ("<== MPInitialize: VELAN %p, Status %x\n", pVElan, Status)); @@ -445,7 +445,7 @@ Arguments: Return Value: - NDIS_STATUS_SUCCESS + NDIS_STATUS_SUCCESS NDIS_STATUS_NOT_SUPPORTED Return code from the MPForwardOidRequest below. @@ -472,14 +472,14 @@ Return Value: DBGPRINT(MUX_LOUD, ("==> MPQueryInformation: VElan %p, Request %p\n",pVElan, NdisRequest)); - + Oid = NdisRequest->DATA.QUERY_INFORMATION.Oid; InformationBuffer = NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer; InformationBufferLength = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength; BytesWritten = (ULONG*) &(NdisRequest->DATA.QUERY_INFORMATION.BytesWritten); BytesNeeded = (ULONG*) &(NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded); - - + + // Initialize the result *BytesWritten = 0; *BytesNeeded = 0; @@ -512,16 +512,16 @@ Return Value: break; case OID_GEN_CURRENT_LOOKAHEAD: - case OID_GEN_MAXIMUM_LOOKAHEAD: + case OID_GEN_MAXIMUM_LOOKAHEAD: ulInfo = pVElan->LookAhead; pInfo = (PVOID) &ulInfo; - break; - + break; + case OID_GEN_MAXIMUM_FRAME_SIZE: ulInfo = ETH_MAX_PACKET_SIZE - ETH_HEADER_SIZE; #if IEEE_VLAN_SUPPORT ulInfo -= VLAN_TAG_HEADER_SIZE; - + #endif pInfo = (PVOID) &ulInfo; break; @@ -532,17 +532,17 @@ Return Value: ulInfo = (ULONG) ETH_MAX_PACKET_SIZE; #if IEEE_VLAN_SUPPORT ulInfo -= VLAN_TAG_HEADER_SIZE; -#endif +#endif pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_MAC_OPTIONS: - ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + ulInfo = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_NO_LOOPBACK; #if IEEE_VLAN_SUPPORT ulInfo |= (NDIS_MAC_OPTION_8021P_PRIORITY | - NDIS_MAC_OPTION_8021Q_VLAN); + NDIS_MAC_OPTION_8021Q_VLAN); #endif pInfo = (PVOID) &ulInfo; break; @@ -555,15 +555,15 @@ Return Value: ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusySends; #if IEEE_VLAN_SUPPORT ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusySends; -#endif +#endif pInfo = (PVOID) &ulInfo; break; case OID_GEN_RECEIVE_BUFFER_SPACE: ulInfo = ETH_MAX_PACKET_SIZE * pVElan->MaxBusyRecvs; #if IEEE_VLAN_SUPPORT - ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusyRecvs; -#endif + ulInfo -= VLAN_TAG_HEADER_SIZE * pVElan->MaxBusyRecvs; +#endif pInfo = (PVOID) &ulInfo; break; @@ -576,7 +576,7 @@ Return Value: pInfo = VendorDesc; ulInfoLen = sizeof(VendorDesc); break; - + case OID_GEN_VENDOR_DRIVER_VERSION: ulInfo = VELAN_VENDOR_ID; pInfo = (PVOID) &ulInfo; @@ -644,7 +644,7 @@ Return Value: NeededLength = sizeof(ulInfo64); break; - + case OID_GEN_RCV_OK: ulInfo64 = pVElan->GoodReceives; pInfo = &ulInfo64; @@ -659,9 +659,9 @@ Return Value: } NeededLength = sizeof(ulInfo64); - + break; - + case OID_GEN_XMIT_ERROR: ulInfo = pVElan->TxAbortExcessCollisions + pVElan->TxDmaUnderrun + @@ -670,7 +670,7 @@ Return Value: pVElan->TransmitFailuresOther; pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_RCV_ERROR: ulInfo = pVElan->RcvCrcErrors + pVElan->RcvAlignmentErrors + @@ -679,26 +679,26 @@ Return Value: #if IEEE_VLAN_SUPPORT ulInfo += (pVElan->RcvVlanIdErrors + - pVElan->RcvFormatErrors); + pVElan->RcvFormatErrors); #endif pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_RCV_NO_BUFFER: ulInfo = pVElan->RcvResourceErrors; pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_RCV_CRC_ERROR: ulInfo = pVElan->RcvCrcErrors; pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_TRANSMIT_QUEUE_LENGTH: ulInfo = pVElan->RegNumTcb; pInfo = (PVOID) &ulInfo; break; - + case OID_GEN_STATISTICS: ulInfoLen = sizeof (NDIS_STATISTICS_INFO); NdisZeroMemory(&StatisticsInfo, sizeof(NDIS_STATISTICS_INFO)); @@ -709,7 +709,7 @@ Return Value: StatisticsInfo.SupportedStatistics = NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR; - + StatisticsInfo.ifInDiscards = (ULONG64)pVElan->RcvCrcErrors + (ULONG64)pVElan->RcvAlignmentErrors + @@ -735,53 +735,53 @@ Return Value: ulInfo = pVElan->RcvAlignmentErrors; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_ONE_COLLISION: ulInfo = pVElan->OneRetry; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_MORE_COLLISIONS: ulInfo = pVElan->MoreThanOneRetry; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_DEFERRED: ulInfo = pVElan->TxOKButDeferred; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_MAX_COLLISIONS: ulInfo = pVElan->TxAbortExcessCollisions; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_RCV_OVERRUN: ulInfo = pVElan->RcvDmaOverrunErrors; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_UNDERRUN: ulInfo = pVElan->TxDmaUnderrun; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_HEARTBEAT_FAILURE: ulInfo = pVElan->TxLostCRS; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_TIMES_CRS_LOST: ulInfo = pVElan->TxLostCRS; pInfo = (PVOID) &ulInfo; break; - + case OID_802_3_XMIT_LATE_COLLISIONS: ulInfo = pVElan->TxLateCollisions; pInfo = (PVOID) &ulInfo; break; - -#if IEEE_VLAN_SUPPORT + +#if IEEE_VLAN_SUPPORT case OID_GEN_VLAN_ID: ulInfo = pVElan->VlanId; pInfo = (PVOID) &ulInfo; @@ -808,27 +808,27 @@ Return Value: if(ulInfoLen) { NdisMoveMemory(InformationBuffer, pInfo, ulInfoLen); - + if (NeededLength > ulInfoLen) { *BytesNeeded = NeededLength; } } - + } else { // too short *BytesNeeded = (NeededLength > ulInfoLen ? NeededLength : ulInfoLen); - + Status = NDIS_STATUS_BUFFER_TOO_SHORT; } } } else { - + // // Send this request to the binding below. @@ -843,10 +843,10 @@ Return Value: pVElan, Oid, Status)); } - + DBGPRINT(MUX_LOUD, ("<== MPQueryInformation: VElan %p, Request %p returning %08lx\n",pVElan, NdisRequest, Status)); - + return(Status); } @@ -887,13 +887,13 @@ Return Value: ULONG InformationBufferLength; PULONG BytesRead; PULONG BytesNeeded; - + // Should we forward the request to the miniport below? BOOLEAN bForwardRequest = FALSE; NDIS_STATUS_INDICATION StatusIndication; DBGPRINT(MUX_LOUD, ("==> MPSetInformation: VElan %p, Request %p\n", pVElan, NdisRequest)); - + NdisZeroMemory(&StatusIndication, sizeof(NDIS_STATUS_INDICATION)); Oid = NdisRequest->DATA.SET_INFORMATION.Oid; InformationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer; @@ -925,48 +925,48 @@ Return Value: Status = NDIS_STATUS_INVALID_LENGTH; break; } - + NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer); - + // // Check if the VELAN adapter goes from lower power state to D0 - // - if ((MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) + // + if ((MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) && (!MUX_IS_LOW_POWER_STATE(NewDeviceState))) { // // Indicate the media status is necessary - // + // if (pVElan->LastIndicatedStatus != pVElan->LatestUnIndicateStatus) { - + StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; StatusIndication.Header.Size = sizeof(NDIS_STATUS_INDICATION); - + StatusIndication.SourceHandle = pVElan->MiniportAdapterHandle; StatusIndication.StatusCode = pVElan->LatestUnIndicateStatus; if (pVElan->LatestUnIndicateStatus == NDIS_STATUS_LINK_STATE) { StatusIndication.StatusBuffer = &pVElan->LatestUnIndicateLinkState; StatusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE); - + } else { StatusIndication.StatusBuffer = NULL; StatusIndication.StatusBufferSize = 0; } - + NdisMIndicateStatusEx(pVElan->MiniportAdapterHandle, &StatusIndication); - + pVElan->LastIndicatedStatus = pVElan->LatestUnIndicateStatus; if (pVElan->LatestUnIndicateStatus == NDIS_STATUS_LINK_STATE) { pVElan->LastIndicatedLinkState = pVElan->LatestUnIndicateLinkState; } - + } else { @@ -976,33 +976,33 @@ Return Value: &pVElan->LastIndicatedLinkState, sizeof(NDIS_LINK_STATE))) { - + StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; StatusIndication.Header.Size = sizeof(NDIS_STATUS_INDICATION); - + StatusIndication.SourceHandle = pVElan->MiniportAdapterHandle; StatusIndication.StatusCode = pVElan->LatestUnIndicateStatus; StatusIndication.StatusBuffer = &pVElan->LatestUnIndicateLinkState; StatusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE); - + NdisMIndicateStatusEx(pVElan->MiniportAdapterHandle, &StatusIndication); pVElan->LastIndicatedStatus = pVElan->LatestUnIndicateStatus; pVElan->LastIndicatedLinkState = pVElan->LatestUnIndicateLinkState; } } - } + } } // // Check if the VELAN adapter goes from D0 to lower power state - // - if ((!MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) + // + if ((!MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) && (MUX_IS_LOW_POWER_STATE(NewDeviceState))) { // - // Initialize LastUnIndicateStatus - // + // Initialize LastUnIndicateStatus + // pVElan->LatestUnIndicateStatus = pVElan->LastIndicatedStatus; if (pVElan->LastIndicatedStatus == NDIS_STATUS_LINK_STATE) @@ -1010,7 +1010,7 @@ Return Value: pVElan->LatestUnIndicateLinkState = pVElan->LastIndicatedLinkState; } } - + NdisMoveMemory(&pVElan->MPDevicePowerState, InformationBuffer, *BytesNeeded); @@ -1062,17 +1062,17 @@ Return Value: pVElan->RestoreLookaheadSize = TRUE; *(UNALIGNED PULONG)InformationBuffer += VLAN_TAG_HEADER_SIZE; } -#endif +#endif bForwardRequest = TRUE; break; - + #if IEEE_VLAN_SUPPORT case OID_GEN_VLAN_ID: if (InformationBufferLength == sizeof(ULONG)) { NdisMoveMemory((&pVElan->VlanId), InformationBuffer, sizeof(ULONG)); - } + } else { *BytesNeeded = sizeof(ULONG); @@ -1081,13 +1081,13 @@ Return Value: break; #endif - + default: Status = NDIS_STATUS_NOT_SUPPORTED; break; } - + if (bForwardRequest == FALSE) { if (Status == NDIS_STATUS_SUCCESS) @@ -1104,7 +1104,7 @@ Return Value: } DBGPRINT(MUX_LOUD, ("<== MPSetInformation: VElan %p, Request %p returning %08lx\n",pVElan, NdisRequest, Status)); - + return(Status); } @@ -1127,7 +1127,7 @@ Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_NOT_SUPPORTED - + --*/ { @@ -1140,7 +1140,7 @@ Return Value: NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNREFERENCED_PARAMETER(pVElan); - + DBGPRINT(MUX_LOUD, ("==> MPMethodRequest: VElan %p, Request %p\n", pVElan, NdisRequest)); @@ -1250,7 +1250,7 @@ Routine Description: Arguments: MiniportAdapterContext Pointer to the pVElan - HaltAction The reason adapter is being halted + HaltAction The reason adapter is being halted Return Value: @@ -1262,7 +1262,7 @@ Return Value: NET_IFINDEX LowerLayerIfIndex; UNREFERENCED_PARAMETER(HaltAction); - + DBGPRINT(MUX_LOUD, ("==> MPHalt: VELAN %p\n", pVElan)); @@ -1316,12 +1316,12 @@ Return Value: if (pVElan->IfIndex != 0) { LowerLayerIfIndex = pVElan->pAdapt->BindParameters.BoundIfIndex; - + NdisIfDeleteIfStackEntry(pVElan->IfIndex, LowerLayerIfIndex); pVElan->IfIndex = 0; } - + // // Unlink the VELAN from its parent ADAPT structure. This will @@ -1329,7 +1329,7 @@ Return Value: // pVElan->MiniportAdapterHandle = NULL; PtUnlinkVElanFromAdapter(pVElan); - + DBGPRINT(MUX_LOUD, ("<== MPHalt: pVElan %p\n", pVElan)); } @@ -1350,7 +1350,7 @@ Routine Description: Arguments: pVElan Pointer to a VElan Adapter - Request Pointer to an NDIS request to be forwarded to the below adapter. + Request Pointer to an NDIS request to be forwarded to the below adapter. Return Value: @@ -1363,7 +1363,7 @@ Return Value: PMUX_NDIS_REQUEST pMuxNdisRequest = &pVElan->Request; PADAPT pAdapt = pVElan->pAdapt; - + DBGPRINT(MUX_LOUD, ("==> MPForwardOidRequest: VELAN %p, Request %p\n", pVElan, Request)); @@ -1373,7 +1373,7 @@ Return Value: // // If the miniport below is going away, fail the request - // + // NdisAcquireSpinLock(&pVElan->Lock); if (pVElan->DeInitializing == TRUE) { @@ -1382,7 +1382,7 @@ Return Value: Status = NDIS_STATUS_FAILURE; break; } - NdisReleaseSpinLock(&pVElan->Lock); + NdisReleaseSpinLock(&pVElan->Lock); // // If the virtual miniport edge is at a low power @@ -1394,14 +1394,14 @@ Return Value: Status = NDIS_STATUS_ADAPTER_NOT_READY; break; } - + NdisAcquireSpinLock(&pVElan->Lock); pMuxNdisRequest->Cancelled = FALSE; pMuxNdisRequest->OrigRequest = Request; pMuxNdisRequest->pCallback = PtCompleteForwardedRequest; pMuxNdisRequest->Request.RequestType = Request->RequestType; pMuxNdisRequest->Refcount = 1; - NdisReleaseSpinLock(&pVElan->Lock); + NdisReleaseSpinLock(&pVElan->Lock); pMuxNdisRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pMuxNdisRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1; @@ -1412,17 +1412,17 @@ Return Value: case NdisRequestQueryInformation: case NdisRequestQueryStatistics: pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Request->DATA.QUERY_INFORMATION.Oid; - pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = + pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = Request->DATA.QUERY_INFORMATION.InformationBuffer; - pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = + pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength; break; case NdisRequestSetInformation: pMuxNdisRequest->Request.DATA.SET_INFORMATION.Oid = Request->DATA.SET_INFORMATION.Oid; - pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBuffer = + pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBuffer = Request->DATA.SET_INFORMATION.InformationBuffer; - pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = + pMuxNdisRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = Request->DATA.SET_INFORMATION.InformationBufferLength; break; @@ -1444,7 +1444,7 @@ Return Value: Status = NDIS_STATUS_FAILURE; break; } - + // If the lower binding has been notified of a low // power state, queue this request; it will be picked // up again when the lower binding returns to D0. @@ -1454,7 +1454,7 @@ Return Value: DBGPRINT(MUX_INFO, ("ForwardRequest: VELAN %p, Adapt %p power" " state is %d, queueing OID %x\n", pVElan, pVElan->pAdapt, - pVElan->pAdapt->PtDevicePowerState, + pVElan->pAdapt->PtDevicePowerState, Request->DATA.QUERY_INFORMATION.Oid)); pVElan->QueuedRequest = TRUE; @@ -1471,19 +1471,19 @@ Return Value: break; } NdisReleaseSpinLock(&pVElan->Lock); - + NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->OutstandingRequests ++; - + if ((pAdapt->Flags & MUX_BINDING_CLOSING)== MUX_BINDING_CLOSING) { - NdisReleaseSpinLock(&pAdapt->Lock); - Status = NDIS_STATUS_CLOSING; + NdisReleaseSpinLock(&pAdapt->Lock); + Status = NDIS_STATUS_CLOSING; } else { - NdisReleaseSpinLock(&pAdapt->Lock); + NdisReleaseSpinLock(&pAdapt->Lock); Status = NdisOidRequest(pVElan->BindingHandle, &pMuxNdisRequest->Request); } @@ -1508,7 +1508,7 @@ Return Value: *(UNALIGNED PULONG)(Request->DATA.SET_INFORMATION.InformationBuffer) -= VLAN_TAG_HEADER_SIZE; } #endif - + return (Status); } @@ -1520,8 +1520,8 @@ MPSetPacketFilter( /*++ Routine Description: - This routine will set up the VELAN so that it accepts packets - that match the specified packet filter. The only filter bits + This routine will set up the VELAN so that it accepts packets + that match the specified packet filter. The only filter bits that can truly be toggled are for broadcast and promiscuous. The MUX driver always sets the lower binding to promiscuous @@ -1529,7 +1529,7 @@ Routine Description: receives too soon. That is, we set the packet filter on the lower binding to a non-zero value iff at least one of the VELANs has a non-zero filter value. - + NOTE: setting the lower binding to promiscuous mode can impact CPU utilization. The only reason we set the lower binding to promiscuous mode in this sample is that we need to be able @@ -1538,18 +1538,18 @@ Routine Description: are set to be equal to that of the adapter below, it is sufficient to set the lower packet filter to the bitwise OR'ed value of packet filter settings on all VELANs. - + Arguments: pVElan - pointer to VELAN - PacketFilter - the new packet filter - + PacketFilter - the new packet filter + Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_NOT_SUPPORTED - + --*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; @@ -1561,7 +1561,7 @@ Return Value: LOCK_STATE LockState; DBGPRINT(MUX_LOUD, ("==> MPSetPacketFilter VELAN %p, Filter %x\n", pVElan, PacketFilter)); - + do { // @@ -1572,7 +1572,7 @@ Return Value: Status = NDIS_STATUS_NOT_SUPPORTED; break; } - + AdapterFilter = 0; pAdapt = pVElan->pAdapt; @@ -1622,7 +1622,7 @@ Return Value: bSendUpdate = TRUE; pAdapt->PacketFilter = MUX_ADAPTER_PACKET_FILTER; } - + MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState); if (bSendUpdate) @@ -1640,7 +1640,7 @@ Return Value: while (FALSE); DBGPRINT(MUX_LOUD, ("<== MPSetPacketFilter VELAN %p, Status %x\n", pVElan, Status)); - + return(Status); } @@ -1718,19 +1718,19 @@ Return Value: NdisZeroMemory(pVElan->McastAddrs, VELAN_MAX_MCAST_LIST * sizeof(MUX_MAC_ADDRESS)); - + NdisMoveMemory(&pVElan->McastAddrs[0], InformationBuffer, InformationBufferLength); - + pVElan->McastAddrCount = InformationBufferLength / sizeof(MUX_MAC_ADDRESS); - + MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState); } while (FALSE); DBGPRINT(MUX_LOUD, ("<== MPSetMulticastList VELAN %p, Status %8x\n", pVElan, Status)); - + return (Status); } @@ -1746,7 +1746,7 @@ Routine Description: Careful! Uses static storage for string. Used to simplify DbgPrints of MAC addresses. - + Arguments: IN Pointer to MAC address array @@ -1755,23 +1755,23 @@ Return Value: A string format of the given mac address ---*/ +--*/ { static UCHAR String[20]; static PCHAR HexChars = "0123456789abcdef"; PUCHAR EthAddr = (PUCHAR) In; UINT i; PUCHAR s; - + for (i = 0, s = String; i < 6; i++, EthAddr++) { -#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "s is bounded by check above"); +#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "s is bounded by check above"); *s++ = HexChars[(*EthAddr) >> 4]; *s++ = HexChars[(*EthAddr) & 0xf]; } *s = '\0'; - - return String; + + return String; } @@ -1788,7 +1788,7 @@ Routine Description: a MAC address for the VELAN. Other implementations are possible, including using the MAC address of the underlying adapter as the MAC address of the VELAN. - + Arguments: pVElan - Pointer to velan structure @@ -1802,7 +1802,7 @@ Return Value: ETH_COPY_NETWORK_ADDRESS( pVElan->CurrentAddress, pVElan->PermanentAddress); - + DBGPRINT(MUX_LOUD, ("%d CurrentAddress %s\n", pVElan->VElanNumber, MacAddrToString(&pVElan->CurrentAddress))); DBGPRINT(MUX_LOUD, ("%d PermanentAddress %s\n", @@ -1838,15 +1838,15 @@ Return Value: { // TBD - add code/comments about processing this. // - + DBGPRINT(MUX_LOUD, ("==> MPDevicePnPEvent: AdapterContext %08lp, DevicePnPEvent %x\n",MiniportAdapterContext, NetDevicePnPEvent->DevicePnPEvent)); UNREFERENCED_PARAMETER(MiniportAdapterContext); UNREFERENCED_PARAMETER(NetDevicePnPEvent); - + DBGPRINT(MUX_LOUD, ("<== MPDevicePnPEvent: AdapterContext %08lp, DevicePnPEvent %x\n",MiniportAdapterContext, NetDevicePnPEvent->DevicePnPEvent)); - + return; } @@ -1882,7 +1882,7 @@ Return Value: UNREFERENCED_PARAMETER(ShutdownAction); DBGPRINT(MUX_LOUD,("<== MPAdapterShutdown: VElan %p, ShutdwonAction %x\n", pVElan, ShutdownAction)); - + return; } @@ -1897,7 +1897,7 @@ Routine Description: This handler is used to unload the miniport Arguments: - DriverObject Pointer to the system's driver object structure + DriverObject Pointer to the system's driver object structure for this driver. Return Value: @@ -1906,11 +1906,11 @@ Return Value: --*/ { - + #if !DBG UNREFERENCED_PARAMETER(DriverObject); #endif - + DBGPRINT(MUX_LOUD, ("==> MPUnload: DriverObj %p\n", DriverObject)); if (ProtHandle != NULL) { @@ -1919,8 +1919,8 @@ Return Value: NdisMDeregisterMiniportDriver(DriverHandle); NdisFreeSpinLock(&GlobalLock); - - DBGPRINT(MUX_LOUD, ("<== MPUnload: DriverObj %p\n", DriverObject)); + + DBGPRINT(MUX_LOUD, ("<== MPUnload: DriverObj %p\n", DriverObject)); } NDIS_STATUS @@ -1947,7 +1947,7 @@ Return Value: NDIS_STATUS Status = NDIS_STATUS_SUCCESS; DBGPRINT(MUX_LOUD, ("==> MPPause: VElan %p\n", pVElan)); - + UNREFERENCED_PARAMETER(MiniportPauseParameters); DBGPRINT(MUX_LOUD,("==>MPPause Adapter %08lp\n",MiniportAdapterContext)); @@ -1960,7 +1960,7 @@ Return Value: NdisReleaseSpinLock(&pVElan->PauseLock); - + DBGPRINT(MUX_LOUD,("<== MPPause,VElan %p, Status %8x\n", pVElan, Status)); @@ -1993,41 +1993,41 @@ Return Value: NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes; PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes; - + UNREFERENCED_PARAMETER(MiniportRestartParameters); DBGPRINT(MUX_LOUD,("==> MPRestart Adapter %p\n",MiniportAdapterContext)); - + // - // Here the driver can change its restart attributes + // Here the driver can change its restart attributes // NdisRestartAttributes = MiniportRestartParameters->RestartAttributes; // // If NdisRestartAttributes is not NULL, then miniport can modify generic attributes and add - // new media specific info attributes at the end. Otherwise, NDIS restarts the miniport because + // new media specific info attributes at the end. Otherwise, NDIS restarts the miniport because // of other reason, miniport should not try to modify/add attributes // if (NdisRestartAttributes != NULL) { ASSERT(NdisRestartAttributes->Oid == OID_GEN_MINIPORT_RESTART_ATTRIBUTES); - + NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; UNREFERENCED_PARAMETER(NdisGeneralAttributes); - + // // Check to see if we need to change any attributes, for example, the driver can change the current // MAC address here. Or the driver can add media specific info attributes. // } - + NdisAcquireSpinLock(&pVElan->PauseLock); pVElan->Paused = FALSE; NdisReleaseSpinLock(&pVElan->PauseLock); - + DBGPRINT(MUX_LOUD,("<== MPRestart: Adapter %p, Status %8x\n", MiniportAdapterContext, Status)); @@ -2066,7 +2066,7 @@ Return Value: PIM_NBL_ENTRY SendContext; ULONG SendCompleteFlags = 0; BOOLEAN DispatchLevel = FALSE; - + DBGPRINT(MUX_VERY_LOUD,("==> MPSendNetBufferLists: MiniportAdapterContext %p, NetBufferLists %p\n",MiniportAdapterContext,NetBufferLists)); DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags); @@ -2078,19 +2078,19 @@ Return Value: NET_BUFFER_LIST_NEXT_NBL(CurrentNetBufferList) = NULL; MUX_ACQUIRE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); - + if (pAdapt->BindingState != MuxAdapterBindingRunning) { Status = NDIS_STATUS_REQUEST_ABORTED; MUX_RELEASE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); - + break; } - + pAdapt->OutstandingSends ++; - + MUX_RELEASE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); - + do { Status = NdisAllocateNetBufferListContext(CurrentNetBufferList, @@ -2102,7 +2102,7 @@ Return Value: { break; } - + SendContext = (PIM_NBL_ENTRY)NET_BUFFER_LIST_CONTEXT_DATA_START(CurrentNetBufferList); NdisZeroMemory(SendContext, sizeof(IM_NBL_ENTRY)); SendContext->PreviousSourceHandle = CurrentNetBufferList->SourceHandle; @@ -2136,20 +2136,20 @@ Return Value: CurrentNetBufferList, PortNumber, SendFlags); - + } while(FALSE); if (Status != NDIS_STATUS_SUCCESS) { MUX_ACQUIRE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); pAdapt->OutstandingSends --; - + if ((pAdapt->OutstandingSends == 0) && (pAdapt->PauseEvent != NULL)) { NdisSetEvent(pAdapt->PauseEvent); pAdapt->PauseEvent = NULL; } - + MUX_RELEASE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); // // Handle failure case @@ -2192,7 +2192,7 @@ Return Value: DBGPRINT(MUX_VERY_LOUD,("<== MPSendNetBufferLists, MiniportAdapterContext %p, NetBufferLists %p\n",MiniportAdapterContext,NetBufferLists)); } -VOID +VOID MPReturnNetBufferLists( IN NDIS_HANDLE MiniportAdapterContext, IN PNET_BUFFER_LIST NetBufferLists, @@ -2218,10 +2218,10 @@ Return Value: PVELAN pVElan = (PVELAN)MiniportAdapterContext; PNET_BUFFER_LIST CurrentNetBufferList = NULL; ULONG NumberOfNetBufferLists = 0; -#ifdef IEEE_VLAN_SUPPORT +#ifdef IEEE_VLAN_SUPPORT NDIS_STATUS Status; #endif - + DBGPRINT(MUX_VERY_LOUD,("==> MPReturnNetBufferLists: MiniportAdapterContext %p, NetBufferList %p\n",MiniportAdapterContext,NetBufferLists)); CurrentNetBufferList = NetBufferLists; @@ -2242,12 +2242,12 @@ Return Value: // Free the context that was allocated in PtReceiveNBL // NdisFreeNetBufferListContext(CurrentNetBufferList, - sizeof(RECV_NBL_ENTRY)); -#endif + sizeof(RECV_NBL_ENTRY)); +#endif CurrentNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentNetBufferList); } - + NdisReturnNetBufferLists(pVElan->BindingHandle, NetBufferLists, ReturnFlags); @@ -2256,9 +2256,9 @@ Return Value: DBGPRINT(MUX_VERY_LOUD,("<== MPReturnNetBufferLists: MiniportAdapterContext %p, NetBufferList %p\n",MiniportAdapterContext,NetBufferLists)); } - -VOID + +VOID MPCancelSendNetBufferLists( IN NDIS_HANDLE MiniportAdapterContext, IN PVOID CancelId @@ -2289,13 +2289,13 @@ Return Value: PVELAN pVElan = (PVELAN)MiniportAdapterContext; DBGPRINT(MUX_LOUD,("==> MPCancelSendNetBufferLists: VElan %p, CancelId %p\n", pVElan, CancelId)); - + NdisCancelSendNetBufferLists(pVElan->pAdapt->BindingHandle,CancelId); - + DBGPRINT(MUX_LOUD,("<== MPCancelSendNetBufferLists: VElan %p, CancelId %p\n", pVElan, CancelId)); } -VOID +VOID MPCancelOidRequest( IN NDIS_HANDLE MiniportAdapterContext, IN PVOID RequestId @@ -2304,9 +2304,9 @@ MPCancelOidRequest( Routine Description: - The miniport entry point to hanadle cancellation of a request. This function + The miniport entry point to hanadle cancellation of a request. This function checks to see if the CancelRequest should be terminated at this level - or passed down to the next driver. + or passed down to the next driver. Arguments: @@ -2321,9 +2321,9 @@ Return Value: PVELAN pVElan = (PVELAN)MiniportAdapterContext; PMUX_NDIS_REQUEST pMuxNdisRequest = &pVElan->Request; BOOLEAN fCancelRequest = FALSE; - + DBGPRINT(MUX_LOUD, ("==> MPCancelOidRequest: VELAN %p, RequestId %p\n", pVElan, RequestId)); - + NdisAcquireSpinLock(&pVElan->Lock); if (pMuxNdisRequest->OrigRequest != NULL) { @@ -2335,22 +2335,22 @@ Return Value: } } - - NdisReleaseSpinLock(&pVElan->Lock); + + NdisReleaseSpinLock(&pVElan->Lock); // - // If we find the request, just send down the cancel, otherwise return because there is only + // If we find the request, just send down the cancel, otherwise return because there is only // one request pending from upper layer on the miniport // if (fCancelRequest) { NdisCancelOidRequest(pVElan->pAdapt->BindingHandle, &pMuxNdisRequest->Request); - PtCompleteForwardedRequest(pVElan->pAdapt, - pMuxNdisRequest, + PtCompleteForwardedRequest(pVElan->pAdapt, + pMuxNdisRequest, NDIS_STATUS_REQUEST_ABORTED); } - + DBGPRINT(MUX_LOUD, ("<== MPCancelOidRequest: VELAN %p, RequestId %p\n", pVElan, RequestId)); } @@ -2365,13 +2365,13 @@ MuxAllocateMdl( /*++ Routine Description: - This function is called by NDIS in order to allocate an MDL and memory when - there isn't unused data space in the net buffer when NdisRetreatNetBufferDataStart + This function is called by NDIS in order to allocate an MDL and memory when + there isn't unused data space in the net buffer when NdisRetreatNetBufferDataStart is called Arguments: BufferSize Pointer to allocation size being requested - + Return Value: NOTE: This function always returns NULL. This is so that MUX can allocate memory and MDL @@ -2384,7 +2384,7 @@ NOTE: This function always returns NULL. This is so that MUX can allocate memory return NULL; } -NDIS_STATUS +NDIS_STATUS MPHandleSendTaggingNB( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList @@ -2420,15 +2420,15 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait PVOID pVa; PMDL Mdl, FirstMdl, SecondMdl, PrevMdl; ULONG BytesToSkip; - ULONG BufferLength; + ULONG BufferLength; PVOID Storage; PNET_BUFFER MdlAllocatedNetBuffers = NULL; DBGPRINT(MUX_LOUD, ("==> MPHandleSendTaggingNB: VELAN %p, NetBufferList %p\n", pVElan, NetBufferList)); - + NdisPacket8021qInfo.Value = NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo); SendContext = (PIM_NBL_ENTRY)NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferList); - + do { Status = NDIS_STATUS_SUCCESS; @@ -2474,7 +2474,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait { // // Find the start address of the frame - // + // Storage = NULL; pEthFrame = NdisGetDataBuffer(CurrentNetBuffer, ETH_HEADER_SIZE, @@ -2490,7 +2490,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait Mdl = NET_BUFFER_CURRENT_MDL(CurrentNetBuffer); PrevMdl = NULL; - + // // Retreat the net buffer list // @@ -2511,7 +2511,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait { // // Advance the NetBuffer so that we can allocate MDLs instead - // + // NdisAdvanceNetBufferDataStart(CurrentNetBuffer, VLAN_TAG_HEADER_SIZE, FALSE, @@ -2520,11 +2520,11 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait Status = NDIS_STATUS_RESOURCES; } } - + if (Status == NDIS_STATUS_RESOURCES) { do - { + { // // There is no more unused data space in the NetBuffer, need to allocate // a new MDL and memory @@ -2537,7 +2537,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // The following loop is to find the start address of the data after // the ethernet header. This may be either in the first MDL // or in the second. - // + // while (TRUE) { pVa = NULL; @@ -2550,7 +2550,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // // Have we gone far enough into the packet? - // + // if (BytesToSkip == 0) { break; @@ -2559,7 +2559,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // // Does the current buffer contain bytes past the Ethernet // header? If so, stop. - // + // if (BufferLength > BytesToSkip) { pVa = (PVOID)((PUCHAR)pVa + BytesToSkip); @@ -2572,7 +2572,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // to the next buffer. // BytesToSkip -= BufferLength; - Mdl = NDIS_MDL_LINKAGE(Mdl); + Mdl = NDIS_MDL_LINKAGE(Mdl); } if (pVa == NULL) @@ -2596,7 +2596,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait } NdisZeroMemory((PVOID)pNetBufferContext, sizeof(IM_SEND_NB_ENTRY)); - + pEthFrameNew = ((PUCHAR) pNetBufferContext) + sizeof(IM_SEND_NB_ENTRY); // @@ -2606,7 +2606,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait SecondMdl = NdisAllocateMdl(pVElan->MiniportAdapterHandle, pVa, // byte following the Eth+tag headers BufferLength); - + FirstMdl = NdisAllocateMdl(pVElan->MiniportAdapterHandle, pEthFrameNew, ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE); @@ -2631,16 +2631,16 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait Status = NDIS_STATUS_RESOURCES; break; } - + // - // All allocations are successful. + // All allocations are successful. // Copy the Ethernet header to the newly allocated memory // Leave space for the VLAN tag // NdisMoveMemory(pEthFrameNew, pEthFrame, 2 * ETH_LENGTH_OF_ADDRESS); - - NdisMoveMemory(pEthFrameNew + (2 * ETH_LENGTH_OF_ADDRESS) + VLAN_TAG_HEADER_SIZE, - pEthFrame + (2 * ETH_LENGTH_OF_ADDRESS), + + NdisMoveMemory(pEthFrameNew + (2 * ETH_LENGTH_OF_ADDRESS) + VLAN_TAG_HEADER_SIZE, + pEthFrame + (2 * ETH_LENGTH_OF_ADDRESS), 2); // @@ -2659,9 +2659,9 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait PrevMdl = NDIS_MDL_LINKAGE(PrevMdl); } - pNetBufferContext->PrevMdl = PrevMdl; + pNetBufferContext->PrevMdl = PrevMdl; } - + pNetBufferContext->CurrentMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(CurrentNetBuffer); // @@ -2685,10 +2685,10 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // Adjust the NetBuffer to use the new Mdls // NDIS_MDL_LINKAGE(FirstMdl) = SecondMdl; - + NDIS_MDL_LINKAGE(SecondMdl) = NDIS_MDL_LINKAGE(Mdl); - - NET_BUFFER_DATA_OFFSET(CurrentNetBuffer) = NET_BUFFER_DATA_OFFSET(CurrentNetBuffer) - + + NET_BUFFER_DATA_OFFSET(CurrentNetBuffer) = NET_BUFFER_DATA_OFFSET(CurrentNetBuffer) - NET_BUFFER_CURRENT_MDL_OFFSET(CurrentNetBuffer); NET_BUFFER_DATA_LENGTH(CurrentNetBuffer) += VLAN_TAG_HEADER_SIZE; @@ -2717,10 +2717,10 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait else if (Status == NDIS_STATUS_SUCCESS) { // - // There was enough unused space in the NetBuffer to - // accomodate the VLAN tag. + // There was enough unused space in the NetBuffer to + // accomodate the VLAN tag. // Get new start address of frame - // + // Storage = NULL; pEthFrameNew = NdisGetDataBuffer(CurrentNetBuffer, VLAN_TAG_HEADER_SIZE, @@ -2734,7 +2734,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait VLAN_TAG_HEADER_SIZE, FALSE, NULL); - + Status = NDIS_STATUS_INVALID_PACKET; } else @@ -2744,14 +2744,14 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait // NdisMoveMemory(pEthFrameNew, pEthFrame, 2 * ETH_LENGTH_OF_ADDRESS); } - + } if (Status != NDIS_STATUS_SUCCESS) { break; } - + pTpid = (PUSHORT)((PUCHAR)pEthFrameNew + 2 * ETH_LENGTH_OF_ADDRESS); *pTpid = TPID; pTagHeader = (PVLAN_TAG_HEADER)(pTpid + 1); @@ -2781,7 +2781,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait { SET_VLAN_ID_TO_TAG(pTagHeader, pVElan->VlanId); } - + CurrentNetBuffer = NET_BUFFER_NEXT_NB(CurrentNetBuffer); } @@ -2789,7 +2789,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait { SendContext->Flags |= MUX_RETREAT_DATA; SendContext->MdlAllocatedNetBuffers = MdlAllocatedNetBuffers; - NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = 0; + NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = 0; } else { @@ -2806,7 +2806,7 @@ NOTE: This functio doesn't handle vlan tagging in an efficient way, please wait return Status; } -VOID +VOID MPRestoreSendNBL( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList, @@ -2825,20 +2825,20 @@ Arguments: Return Value: --*/ - + { PNET_BUFFER CurrentNetBuffer; PNET_BUFFER CurrentMdlAllocatedNetBuffer, SavedMdlAllocatedNetBuffer; PIM_SEND_NB_ENTRY NetBufferContext; PVOID pVa = NULL; ULONG BufferLength; - PUCHAR pFrame = NULL, pDst = NULL; + PUCHAR pFrame = NULL, pDst = NULL; PMDL FirstMdl, SecondMdl; PVOID Storage; CurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList); CurrentMdlAllocatedNetBuffer = MdlAllocatedNetBuffers; - + while (CurrentNetBuffer != LastNetBuffer) { SavedMdlAllocatedNetBuffer = CurrentMdlAllocatedNetBuffer; @@ -2848,9 +2848,9 @@ Return Value: // if (CurrentMdlAllocatedNetBuffer) { - NdisQueryMdl(NET_BUFFER_CURRENT_MDL(CurrentMdlAllocatedNetBuffer), - &pVa, - &BufferLength, + NdisQueryMdl(NET_BUFFER_CURRENT_MDL(CurrentMdlAllocatedNetBuffer), + &pVa, + &BufferLength, NormalPagePriority | MdlMappingNoExecute); if( pVa == NULL ){ //you may do something @@ -2872,10 +2872,10 @@ Return Value: //check why NetBufferContext is NULL } else{ - NET_BUFFER_DATA_OFFSET(CurrentMdlAllocatedNetBuffer) = NET_BUFFER_DATA_OFFSET(CurrentMdlAllocatedNetBuffer) + + NET_BUFFER_DATA_OFFSET(CurrentMdlAllocatedNetBuffer) = NET_BUFFER_DATA_OFFSET(CurrentMdlAllocatedNetBuffer) + NetBufferContext->CurrentMdlOffset; - - NET_BUFFER_DATA_LENGTH(CurrentMdlAllocatedNetBuffer) -= VLAN_TAG_HEADER_SIZE; + + NET_BUFFER_DATA_LENGTH(CurrentMdlAllocatedNetBuffer) -= VLAN_TAG_HEADER_SIZE; NET_BUFFER_CURRENT_MDL_OFFSET(CurrentMdlAllocatedNetBuffer) = NetBufferContext->CurrentMdlOffset; @@ -2889,22 +2889,22 @@ Return Value: { NET_BUFFER_FIRST_MDL(CurrentMdlAllocatedNetBuffer) = NetBufferContext->CurrentMdl; } - - CurrentMdlAllocatedNetBuffer = NetBufferContext->NextNetBuffer; + + CurrentMdlAllocatedNetBuffer = NetBufferContext->NextNetBuffer; // // Free the MDLs and the memory allocated // - NdisFreeMdl(SecondMdl); + NdisFreeMdl(SecondMdl); NdisFreeMdl(FirstMdl); - NdisFreeToNPagedLookasideList(&pVElan->TagLookaside, (PVOID) NetBufferContext); + NdisFreeToNPagedLookasideList(&pVElan->TagLookaside, (PVOID) NetBufferContext); } } // - // Advance the NET_BUFFERs until the NET_BUFFER for which + // Advance the NET_BUFFERs until the NET_BUFFER for which // the MDLs were allocated // while ((CurrentNetBuffer != SavedMdlAllocatedNetBuffer) && @@ -2930,13 +2930,13 @@ Return Value: RtlMoveMemory(pDst, pFrame, (2 * ETH_LENGTH_OF_ADDRESS)); } - + NdisAdvanceNetBufferDataStart(CurrentNetBuffer, VLAN_TAG_HEADER_SIZE, FALSE, - NULL); - - CurrentNetBuffer = NET_BUFFER_NEXT_NB(CurrentNetBuffer); + NULL); + + CurrentNetBuffer = NET_BUFFER_NEXT_NB(CurrentNetBuffer); } if (SavedMdlAllocatedNetBuffer) diff --git a/network/ndis/mux/driver/60/mux.c b/network/ndis/mux/driver/60/mux.c index 1ff8698b..4654d373 100644 --- a/network/ndis/mux/driver/60/mux.c +++ b/network/ndis/mux/driver/60/mux.c @@ -1,8 +1,8 @@ /*++ Copyright (c) 1992-2000 Microsoft Corporation - + Module Name: - + mux.c Abstract: @@ -31,7 +31,7 @@ Revision History: #if DBG // // Debug level for mux driver -// +// INT muxDebugLevel = MUX_WARN; #endif //DBG @@ -103,9 +103,9 @@ Arguments: DriverObject - pointer to the system's driver object structure for this driver - + RegistryPath - system's registry path for this driver - + Return Value: STATUS_SUCCESS if all initialization is successful, STATUS_XXX @@ -119,13 +119,13 @@ Return Value: NDIS_HANDLE MiniportDriverContext; NDIS_HANDLE ProtocolDriverContext; NDIS_STRING Name; - + NdisInitializeListHead(&AdapterList); NdisInitializeListHead(&VElanList); MiniportDriverContext=NULL; ProtocolDriverContext=NULL; - + MUX_INIT_MUTEX(&GlobalMutex); MUX_INIT_MUTEX(&ControlDeviceMutex); NdisAllocateSpinLock(&GlobalLock); @@ -147,7 +147,7 @@ Return Value: MChars.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; MChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS); MChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1; - + MChars.MajorNdisVersion = MUX_MAJOR_NDIS_VERSION; MChars.MinorNdisVersion = MUX_MINOR_NDIS_VERSION; @@ -198,15 +198,15 @@ Return Value: PChars.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; PChars.Header.Size = sizeof(NDIS_PROTOCOL_DRIVER_CHARACTERISTICS); PChars.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; - + PChars.MajorNdisVersion = MUX_PROT_MAJOR_NDIS_VERSION; PChars.MinorNdisVersion = MUX_PROT_MINOR_NDIS_VERSION; - + PChars.MajorDriverVersion = MUX_MAJOR_DRIVER_VERSION; PChars.MinorDriverVersion = MUX_MINOR_DRIVER_VERSION; PChars.SetOptionsHandler = PtSetOptions; - + // // Make sure the protocol-name matches the service-name // (from the INF) under which this protocol is installed. @@ -254,11 +254,11 @@ MpSetOptions( Routine Description: This routine registers the optional handlers for the MUX MINIPORT driver with NDIS. - + Arguments: NdisDriverHandle Mux miniport driver handle - DriverContext Specifies a handle to a driver-allocated context area where the driver + DriverContext Specifies a handle to a driver-allocated context area where the driver maintains state and configuration information Return Value: @@ -283,11 +283,11 @@ PtSetOptions( Routine Description: This routine registers the optional handlers for the MUX PROTOCOL driver with NDIS. - + Arguments: NdisDriverHandle Mux protocol driver handle - DriverContext Specifies a handle to a driver-allocated context area where the driver + DriverContext Specifies a handle to a driver-allocated context area where the driver maintains state and configuration information Return Value: @@ -346,16 +346,16 @@ Return Value: MUX_ACQUIRE_MUTEX(&ControlDeviceMutex); ++MiniportCount; - + if (1 == MiniportCount) { NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); - + DispatchTable[IRP_MJ_CREATE] = PtDispatch; DispatchTable[IRP_MJ_CLEANUP] = PtDispatch; DispatchTable[IRP_MJ_CLOSE] = PtDispatch; DispatchTable[IRP_MJ_DEVICE_CONTROL] = PtDispatch; - + NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, GLOBAL_LINKNAME_STRING); @@ -377,7 +377,7 @@ Return Value: &DeviceObjectAttributes, &ControlDeviceObject, &NdisDeviceHandle); - + } MUX_RELEASE_MUTEX(&ControlDeviceMutex); @@ -416,36 +416,36 @@ Return Value: PVOID buffer; UNREFERENCED_PARAMETER(DeviceObject); - + irpStack = IoGetCurrentIrpStackLocation(Irp); DBGPRINT(MUX_LOUD, ("==>PtDispatch %d\n", irpStack->MajorFunction)); - + switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: break; - + case IRP_MJ_CLEANUP: break; - + case IRP_MJ_CLOSE: - break; - - case IRP_MJ_DEVICE_CONTROL: + break; + + case IRP_MJ_DEVICE_CONTROL: { - - buffer = Irp->AssociatedIrp.SystemBuffer; + + buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; UNREFERENCED_PARAMETER(buffer); UNREFERENCED_PARAMETER(inlen); - - switch (irpStack->Parameters.DeviceIoControl.IoControlCode) + + switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { // // Add code here to handle ioctl commands. // } - break; + break; } default: break; @@ -458,7 +458,7 @@ Return Value: return status; -} +} NDIS_STATUS @@ -492,7 +492,7 @@ Return Value: ASSERT(MiniportCount > 0); --MiniportCount; - + if (0 == MiniportCount) { // @@ -511,6 +511,6 @@ Return Value: DBGPRINT(MUX_INFO, ("<== PtDeregisterDevice: %x\n", Status)); return Status; - + } diff --git a/network/ndis/mux/driver/60/mux.h b/network/ndis/mux/driver/60/mux.h index dcdef937..a36ee52d 100644 --- a/network/ndis/mux/driver/60/mux.h +++ b/network/ndis/mux/driver/60/mux.h @@ -124,7 +124,7 @@ VOID #define MUX_ADAPTER_PACKET_FILTER \ NDIS_PACKET_TYPE_PROMISCUOUS - + #define MIN_PACKET_POOL_SIZE 255 #define MAX_PACKET_POOL_SIZE 4096 @@ -466,7 +466,7 @@ typedef struct _ADAPT NDIS_MEDIUM Medium ; // - // BindParameters passed to protocol giving it information on + // BindParameters passed to protocol giving it information on // the miniport below // NDIS_BIND_PARAMETERS BindParameters; @@ -474,7 +474,7 @@ typedef struct _ADAPT NDIS_RECEIVE_SCALE_CAPABILITIES RcvScaleCapabilities; NDIS_LINK_STATE LastIndicatedLinkState; MUX_ADAPTER_BINDING_STATE BindingState; - + ULONG OutstandingSends; PNDIS_EVENT PauseEvent; NDIS_SPIN_LOCK Lock; @@ -552,7 +552,7 @@ typedef struct _VELAN // serializes requests to a miniport, we only need one of these // per VELAN. // - MUX_NDIS_REQUEST Request; + MUX_NDIS_REQUEST Request; // Have we queued a request because the lower binding is // at a low power state? BOOLEAN QueuedRequest; @@ -609,7 +609,7 @@ typedef struct _VELAN // Multicast list MUX_MAC_ADDRESS McastAddrs[VELAN_MAX_MCAST_LIST]; ULONG McastAddrCount; - + NDIS_STATUS LastIndicatedStatus; NDIS_STATUS LatestUnIndicateStatus; @@ -626,7 +626,7 @@ typedef struct _VELAN ULONG RcvFormatErrors; ULONG RcvVlanIdErrors; BOOLEAN RestoreLookaheadSize; - NPAGED_LOOKASIDE_LIST TagLookaside; + NPAGED_LOOKASIDE_LIST TagLookaside; #endif NET_IFINDEX IfIndex; @@ -661,22 +661,22 @@ typedef struct _VELAN #if IEEE_VLAN_SUPPORT -#define TPID 0x0081 +#define TPID 0x0081 // // Define tag_header structure // typedef struct _VLAN_TAG_HEADER { - UCHAR TagInfo[2]; + UCHAR TagInfo[2]; } VLAN_TAG_HEADER, *PVLAN_TAG_HEADER; // // Macro definitions for VLAN support -// -#define VLAN_TAG_HEADER_SIZE 4 +// +#define VLAN_TAG_HEADER_SIZE 4 -#define VLANID_DEFAULT 0 +#define VLANID_DEFAULT 0 #define VLAN_ID_MAX 0xfff #define VLAN_ID_MIN 0x0 @@ -686,7 +686,7 @@ typedef struct _VLAN_TAG_HEADER // // Get information for tag headre -// +// #define GET_CANONICAL_FORMAT_ID_FROM_TAG(_pTagHeader) \ ((_pTagHeader)->TagInfo[0] & CANONICAL_FORMAT_ID_MASK) @@ -698,23 +698,23 @@ typedef struct _VLAN_TAG_HEADER // // Clear the tag header struct -// +// #define INITIALIZE_TAG_HEADER_TO_ZERO(_pTagHeader) \ { \ (_pTagHeader)->TagInfo[0] = 0; \ (_pTagHeader)->TagInfo[1] = 0; \ } - + // // Set VLAN information to tag header // Before we called all the set macro, first we need to initialize pTagHeader to be 0 // #define SET_CANONICAL_FORMAT_ID_TO_TAG(_pTagHeader, _CanonicalFormatId) \ (_pTagHeader)->TagInfo[0] |= ((UCHAR)(_CanonicalFormatId) << 4) - + #define SET_USER_PRIORITY_TO_TAG(_pTagHeader, _UserPriority) \ (_pTagHeader)->TagInfo[0] |= ((UCHAR)(_UserPriority) << 5) - + #define SET_VLAN_ID_TO_TAG(_pTagHeader, _VlanId) \ { \ (_pTagHeader)->TagInfo[0] |= (((UCHAR)((_VlanId) >> 8)) & 0x0f); \ @@ -724,7 +724,7 @@ typedef struct _VLAN_TAG_HEADER // // Copy tagging information in the indicated frame to per packet info -// +// #define COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(_Ieee8021qInfo, _pTagHeader) \ { \ (_Ieee8021qInfo).TagHeader.UserPriority = ((_pTagHeader->TagInfo[0] & USER_PRIORITY_MASK) >> 5); \ @@ -744,7 +744,7 @@ typedef struct _VLAN_TAG_HEADER // // Every NBL that is indicated up to a protocol needs to advance the buffer -// in case the VLAN tag is present. It should be restored before returning the +// in case the VLAN tag is present. It should be restored before returning the // packet to the miniport. This structure is used for that purpose // typedef struct _RECV_NBL_ENTRY @@ -770,11 +770,11 @@ typedef struct _IM_SEND_NB_ENTRY #endif //IEEE_VLAN_SUPPORT -typedef struct _IM_NBL_ENTRY +typedef struct _IM_NBL_ENTRY { NDIS_HANDLE PreviousSourceHandle; PVELAN pVElan; -#if IEEE_VLAN_SUPPORT +#if IEEE_VLAN_SUPPORT ULONG Flags; PNET_BUFFER MdlAllocatedNetBuffers; #endif @@ -847,7 +847,7 @@ typedef struct _IM_NBL_ENTRY #define ASSERT_AT_PASSIVE() \ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL) - + #define ASSERT_AT_DISPATCH() \ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL) @@ -912,13 +912,13 @@ MuxAllocateMdl( IN OUT PULONG BufferSize ); -NDIS_STATUS +NDIS_STATUS MPHandleSendTaggingNB( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList ); -VOID +VOID MPRestoreSendNBL( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList, @@ -926,21 +926,21 @@ MPRestoreSendNBL( IN PNET_BUFFER MdlAllocatedNetBuffers ); -NDIS_STATUS +NDIS_STATUS PtHandleReceiveTaggingNB( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList, - IN PNDIS_NET_BUFFER_LIST_8021Q_INFO NdisPacket8021qInfo + IN PNDIS_NET_BUFFER_LIST_8021Q_INFO NdisPacket8021qInfo ); -NDIS_STATUS +NDIS_STATUS PtStripVlanTagNB( IN PNET_BUFFER_LIST NetBufferList, OUT PNDIS_NET_BUFFER_LIST_8021Q_INFO NdisPacket8021qInfo, - OUT PRECV_NBL_ENTRY RecvContext + OUT PRECV_NBL_ENTRY RecvContext ); -NDIS_STATUS +NDIS_STATUS PtRestoreReceiveNBL( IN PNET_BUFFER_LIST NetBufferList ); diff --git a/network/ndis/mux/driver/60/protocol.c b/network/ndis/mux/driver/60/protocol.c index 908e4de2..8a697c04 100644 --- a/network/ndis/mux/driver/60/protocol.c +++ b/network/ndis/mux/driver/60/protocol.c @@ -1,5 +1,5 @@ /*++ -Copyright(c) 1992-2000 Microsoft Corporation +Copyright (c) 1992-2000 Microsoft Corporation Module Name: @@ -67,11 +67,11 @@ Return Value: UNREFERENCED_PARAMETER(ProtocolDriverContext); UNREFERENCED_PARAMETER(BindContext); - + pConfigString = (PNDIS_STRING)BindParameters->ProtocolSection; - + DBGPRINT(MUX_LOUD, ("==> Protocol BindAdapter: %ws\n", pConfigString->Buffer)); - + do { if (BindParameters->Header.Type != NDIS_OBJECT_TYPE_BIND_PARAMETERS || @@ -80,12 +80,12 @@ Return Value: Status = NDIS_STATUS_INVALID_PARAMETER; break; } - + // // Allocate memory for Adapter struct plus the config // string with two extra WCHARs for NULL termination. // - Length = sizeof(ADAPT) + + Length = sizeof(ADAPT) + pConfigString->MaximumLength + sizeof(WCHAR); pAdapt = NdisAllocateMemoryWithTagPriority(ProtHandle, Length , MUX_TAG, LowPoolPriority); @@ -94,14 +94,14 @@ Return Value: Status = NDIS_STATUS_RESOURCES; break; } - + // // Initialize the adapter structure // - NdisZeroMemory(pAdapt, sizeof(ADAPT)); + NdisZeroMemory(pAdapt, sizeof(ADAPT)); + + (VOID)PtReferenceAdapter(pAdapt, (PUCHAR)"openadapter"); - (VOID)PtReferenceAdapter(pAdapt, (PUCHAR)"openadapter"); - // // Copy in the Config string - we will use this to open the @@ -109,13 +109,13 @@ Return Value: // pAdapt->ConfigString.MaximumLength = pConfigString->MaximumLength; pAdapt->ConfigString.Length = pConfigString->Length; - pAdapt->ConfigString.Buffer = (PWCHAR)((PUCHAR)pAdapt + + pAdapt->ConfigString.Buffer = (PWCHAR)((PUCHAR)pAdapt + sizeof(ADAPT)); NdisMoveMemory(pAdapt->ConfigString.Buffer, pConfigString->Buffer, pConfigString->Length); - pAdapt->ConfigString.Buffer[pConfigString->Length/sizeof(WCHAR)] = + pAdapt->ConfigString.Buffer[pConfigString->Length/sizeof(WCHAR)] = ((WCHAR)0); NdisInitializeEvent(&pAdapt->Event); @@ -173,9 +173,9 @@ Return Value: break; } pAdapt->Flags |= MUX_BINDING_ACTIVE; - + pAdapt->BindingState = MuxAdapterBindingPaused; - + pAdapt->Medium = MediumArray[MediumIndex]; // @@ -188,20 +188,20 @@ Return Value: MUX_RELEASE_MUTEX(&GlobalMutex); // - // Copy all the relevant information about the Adapter into + // Copy all the relevant information about the Adapter into // the local structure // pAdapt->BindParameters = *BindParameters; - + if (BindParameters->RcvScaleCapabilities) { pAdapt->RcvScaleCapabilities = (*BindParameters->RcvScaleCapabilities); pAdapt->BindParameters.RcvScaleCapabilities = &pAdapt->RcvScaleCapabilities; } - - pAdapt->PowerManagementCapabilities = (*BindParameters->PowerManagementCapabilities); - + pAdapt->PowerManagementCapabilities = (*BindParameters->PowerManagementCapabilities); + + PtPostProcessPnPCapabilities(&pAdapt->PowerManagementCapabilities, sizeof(pAdapt->PowerManagementCapabilities)); @@ -211,7 +211,7 @@ Return Value: pAdapt->BindParameters.ProtocolSection= NULL; pAdapt->BindParameters.AdapterName = NULL; pAdapt->BindParameters.PhysicalDeviceObject = NULL; - + // // Start all VELANS configured on this adapter. // @@ -222,12 +222,12 @@ Return Value: break; } - + } while(FALSE); if (Status != NDIS_STATUS_SUCCESS) { - + if (pAdapt != NULL) { // @@ -237,7 +237,7 @@ Return Value: { // // Close the binding the driver opened above - // + // PtCloseAdapter(pAdapt); MUX_ACQUIRE_MUTEX(&GlobalMutex); @@ -250,7 +250,7 @@ Return Value: pAdapt = NULL; } } - + DBGPRINT(MUX_INFO, ("<== PtBindAdapter: pAdapt %p, Status %x\n", pAdapt, Status)); @@ -268,7 +268,7 @@ PtOpenAdapterComplete( Routine Description: - Completion routine for NdisOpenAdapter issued from within the + Completion routine for NdisOpenAdapter issued from within the PtBindAdapter. Simply unblock the caller. Arguments: @@ -318,7 +318,7 @@ Return Value: // Insert code here to query Adapter info if needed // UNREFERENCED_PARAMETER(pAdapt); - + } @@ -370,7 +370,7 @@ Return Value: // pMuxNdisRequest->pCallback = PtCompleteBlockingRequest; NdisInitializeEvent(&pMuxNdisRequest->Event); - + pMuxNdisRequest->Request.Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pMuxNdisRequest->Request.Header.Revision = NDIS_OID_REQUEST_REVISION_1; pMuxNdisRequest->Request.Header.Size = sizeof(NDIS_OID_REQUEST); @@ -381,29 +381,29 @@ Return Value: InformationBuffer; pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; - + NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->OutstandingRequests ++; - + if ((pAdapt->Flags & MUX_BINDING_CLOSING)== MUX_BINDING_CLOSING) { Status = NDIS_STATUS_CLOSING; - NdisReleaseSpinLock(&pAdapt->Lock); + NdisReleaseSpinLock(&pAdapt->Lock); } else { NdisReleaseSpinLock(&pAdapt->Lock); Status = NdisOidRequest(pAdapt->BindingHandle, - &pMuxNdisRequest->Request); + &pMuxNdisRequest->Request); } if (Status != NDIS_STATUS_PENDING) { NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->OutstandingRequests --; - + if ((pAdapt->OutstandingRequests == 0) && (pAdapt->CloseEvent != NULL)) { NdisSetEvent(pAdapt->CloseEvent); @@ -411,11 +411,11 @@ Return Value: } NdisReleaseSpinLock(&pAdapt->Lock); } - else + else { NdisWaitEvent(&pMuxNdisRequest->Event, 0); Status = pMuxNdisRequest->Status; - } + } } while (FALSE); @@ -496,7 +496,7 @@ Return Value: InformationBuffer; pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; - + break; case NdisRequestSetInformation: @@ -505,31 +505,31 @@ Return Value: InformationBuffer; pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; - + break; - + default: ASSERT(FALSE); break; } - + NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->OutstandingRequests ++; - + if ((pAdapt->Flags & MUX_BINDING_CLOSING)== MUX_BINDING_CLOSING) { - NdisReleaseSpinLock(&pAdapt->Lock); - Status = NDIS_STATUS_CLOSING; + NdisReleaseSpinLock(&pAdapt->Lock); + Status = NDIS_STATUS_CLOSING; } else { - NdisReleaseSpinLock(&pAdapt->Lock); + NdisReleaseSpinLock(&pAdapt->Lock); Status = NdisOidRequest( pAdapt->BindingHandle, pNdisRequest); } - + if (Status != NDIS_STATUS_PENDING) { PtRequestComplete( @@ -553,13 +553,13 @@ PtCloseAdapter( Routine Description: - Call either when the protocol is unbinding or the miniport is halting to set + Call either when the protocol is unbinding or the miniport is halting to set the packet filters back to zero and multicast filter back to zero Arguments: pAdapter Pointer to a virtual adapter - + Return Value: None @@ -573,7 +573,7 @@ Return Value: NDIS_EVENT CloseEvent; DBGPRINT(MUX_LOUD, ("==> PtCloseAdapter: Adapt %p\n", pAdapt)); - + ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); // @@ -581,15 +581,15 @@ Return Value: // from the adapter below is required for NDIS 6.0 protocols // PtRequestAdapterSync(pAdapt, - NdisRequestSetInformation, + NdisRequestSetInformation, OID_GEN_CURRENT_PACKET_FILTER, - &PacketFilter, + &PacketFilter, sizeof(PacketFilter)); PtRequestAdapterSync(pAdapt, - NdisRequestSetInformation, + NdisRequestSetInformation, OID_802_3_MULTICAST_LIST, - MCastBuf, + MCastBuf, MCastBufSize); // // Stop sending requests and wait for outstanding requests to complete @@ -602,16 +602,16 @@ Return Value: if (pAdapt->OutstandingRequests != 0) { NdisInitializeEvent(&CloseEvent); - pAdapt->CloseEvent = &CloseEvent; + pAdapt->CloseEvent = &CloseEvent; NdisReleaseSpinLock(&pAdapt->Lock); - NdisWaitEvent(&CloseEvent, 0); + NdisWaitEvent(&CloseEvent, 0); NdisAcquireSpinLock(&pAdapt->Lock); } NdisReleaseSpinLock(&pAdapt->Lock); // // Now Close the binding with the adapter below // - + NdisResetEvent(&pAdapt->Event); Status = NdisCloseAdapterEx(pAdapt->BindingHandle); @@ -625,7 +625,7 @@ Return Value: } pAdapt->BindingHandle = NULL; - + DBGPRINT(MUX_LOUD, ("<== PtCloseAdapter: Adapt %p\n", pAdapt)); } @@ -660,7 +660,7 @@ Return Value: NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNREFERENCED_PARAMETER(UnbindContext); - + DBGPRINT(MUX_LOUD, ("==> PtUnbindAdapter: Adapt %p\n", pAdapt)); // @@ -700,9 +700,9 @@ Return Value: // run StopVElan at passive IRQL. // MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState); - + PtStopVElan(pVElan); - + PtDereferenceVElan(pVElan, (PUCHAR)"UnbindTemp"); MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState); @@ -755,7 +755,7 @@ Return Value: // // Remove the adapter from the global AdapterList // - + MUX_ACQUIRE_MUTEX(&GlobalMutex); RemoveEntryList(&pAdapt->Link); @@ -763,16 +763,16 @@ Return Value: MUX_RELEASE_MUTEX(&GlobalMutex); NdisFreeSpinLock(&pAdapt->Lock); - + // // Free all the resources associated with this Adapter except the - // ADAPT struct itself, because that will be freed by - // PtDereferenceAdapter call when the reference drops to zero. + // ADAPT struct itself, because that will be freed by + // PtDereferenceAdapter call when the reference drops to zero. // Note: Every VELAN associated with this Adapter takes a ref count // on it. So the adapter memory wouldn't be freed until all the VELANs - // are shutdown. + // are shutdown. // - + PtDereferenceAdapter(pAdapt, (PUCHAR)"Unbind"); DBGPRINT(MUX_LOUD, ("<== PtUnbindAdapter: Adapt %p, Status=%08lx\n", pAdapt, Status)); @@ -795,7 +795,7 @@ Routine Description: Arguments: ProtocolBindingContext Pointer to the adapter structure - + Return Value: None. @@ -804,12 +804,12 @@ Return Value: { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; - DBGPRINT(MUX_LOUD, ("==> PtCloseAdapterComplete: Adapt %p\n", + DBGPRINT(MUX_LOUD, ("==> PtCloseAdapterComplete: Adapt %p\n", pAdapt)); NdisSetEvent(&pAdapt->Event); - DBGPRINT(MUX_LOUD, ("<== PtCloseAdapterComplete: Adapt %p\n", + DBGPRINT(MUX_LOUD, ("<== PtCloseAdapterComplete: Adapt %p\n", pAdapt)); } @@ -843,27 +843,27 @@ Return Value: PMUX_NDIS_REQUEST pMuxNdisRequest; - DBGPRINT(MUX_LOUD, ("==> PtRequestComplete: Adapt %p, Request %p, Status %8x\n", + DBGPRINT(MUX_LOUD, ("==> PtRequestComplete: Adapt %p, Request %p, Status %8x\n", pAdapt, NdisRequest, Status)); //get the Super-structure for NDIS_REQUEST before getting the callback functions //so make sure NdisRequest is a filled into a MUX_NDIS_REQUEST before using this function pMuxNdisRequest = CONTAINING_RECORD(NdisRequest, MUX_NDIS_REQUEST, Request); - + ASSERT(pMuxNdisRequest->pCallback != NULL); - + // // Completion is handled by the callback routine: // - (*pMuxNdisRequest->pCallback)(pAdapt, + (*pMuxNdisRequest->pCallback)(pAdapt, pMuxNdisRequest, Status); NdisAcquireSpinLock(&pAdapt->Lock); - + pAdapt->OutstandingRequests --; - + if ((pAdapt->OutstandingRequests == 0) && (pAdapt->CloseEvent != NULL)) { NdisSetEvent(pAdapt->CloseEvent); @@ -872,7 +872,7 @@ Return Value: NdisReleaseSpinLock(&pAdapt->Lock); - DBGPRINT(MUX_LOUD, ("<== PtRequestComplete: Adapt %p, Request %p, Status %8x\n", + DBGPRINT(MUX_LOUD, ("<== PtRequestComplete: Adapt %p, Request %p, Status %8x\n", pAdapt, NdisRequest, Status)); } @@ -914,9 +914,9 @@ Return Value: BOOLEAN fCompleteRequest = FALSE; UNREFERENCED_PARAMETER(pAdapt); - - DBGPRINT(MUX_LOUD, ("==> PtCompleteForwardedRequest: Adapt %p, MuxRequest %p, Status %8x\n", + + DBGPRINT(MUX_LOUD, ("==> PtCompleteForwardedRequest: Adapt %p, MuxRequest %p, Status %8x\n", pAdapt, pMuxNdisRequest, Status)); // // Get the originating VELAN. The VELAN will not be dereferenced @@ -926,10 +926,10 @@ Return Value: ASSERT(pVElan != NULL); ASSERT(pMuxNdisRequest == &pVElan->Request); - + if (Status != NDIS_STATUS_SUCCESS) { - DBGPRINT(MUX_WARN, ("PtCompleteForwardedRequest: pVElan %p, OID %x, Status %x\n", + DBGPRINT(MUX_WARN, ("PtCompleteForwardedRequest: pVElan %p, OID %x, Status %x\n", pVElan, pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid, Status)); @@ -944,9 +944,9 @@ Return Value: OrigRequest = pMuxNdisRequest->OrigRequest; pMuxNdisRequest->OrigRequest = NULL; } - - NdisReleaseSpinLock(&pVElan->Lock); + + NdisReleaseSpinLock(&pVElan->Lock); if (fCompleteRequest == FALSE) { @@ -961,9 +961,9 @@ Return Value: case NdisRequestQueryInformation: case NdisRequestQueryStatistics: - OrigRequest->DATA.QUERY_INFORMATION.BytesWritten = + OrigRequest->DATA.QUERY_INFORMATION.BytesWritten = pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten; - OrigRequest->DATA.QUERY_INFORMATION.BytesNeeded = + OrigRequest->DATA.QUERY_INFORMATION.BytesNeeded = pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded; // @@ -995,8 +995,8 @@ Return Value: OrigRequest->DATA.QUERY_INFORMATION.BytesNeeded= pNdisRequest->DATA.SET_INFORMATION.BytesNeeded; -#if IEEE_VELAN_SUPPORT - if ((pNdisRequest->DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_LOOKAHEAD) +#if IEEE_VELAN_SUPPORT + if ((pNdisRequest->DATA.SET_INFORMATION.Oid == OID_GEN_CURRENT_LOOKAHEAD) && (pVElan->RestoreLookaheadSize == TRUE)) { pVElan->RestoreLookaheadSize = FALSE; @@ -1013,8 +1013,8 @@ Return Value: switch (Oid) { case OID_GEN_CURRENT_LOOKAHEAD: - - + + NdisMoveMemory(&pVElan->LookAhead, pNdisRequest->DATA.SET_INFORMATION.InformationBuffer, sizeof(ULONG)); @@ -1036,7 +1036,7 @@ Return Value: MUX_DECR_PENDING_SENDS(pVElan); - DBGPRINT(MUX_LOUD, ("<== PtCompleteForwardedRequest: Adapt %p, MuxRequest %p, Status %8x\n", + DBGPRINT(MUX_LOUD, ("<== PtCompleteForwardedRequest: Adapt %p, MuxRequest %p, Status %8x\n", pAdapt, pMuxNdisRequest, Status)); } @@ -1070,7 +1070,7 @@ Return Value: PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct; DBGPRINT(MUX_LOUD, ("==> PtPostProcessPnPCapabilities\n")); - + if (InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES)) { pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)InformationBuffer; @@ -1114,9 +1114,9 @@ Return Value: { UNREFERENCED_PARAMETER(pAdapt); - DBGPRINT(MUX_LOUD, ("==> PtCompleteBlockingRequest: Adapt %p, MuxRequest %p, Status %8x\n", + DBGPRINT(MUX_LOUD, ("==> PtCompleteBlockingRequest: Adapt %p, MuxRequest %p, Status %8x\n", pAdapt, pMuxNdisRequest, Status)); - + // // The request was originated from this driver. Wake up the // thread blocked for its completion. @@ -1124,7 +1124,7 @@ Return Value: pMuxNdisRequest->Status = Status; NdisSetEvent(&pMuxNdisRequest->Event); - DBGPRINT(MUX_LOUD, ("<== PtCompleteBlockingRequest: Adapt %p, MuxRequest %p, Status %8x\n", + DBGPRINT(MUX_LOUD, ("<== PtCompleteBlockingRequest: Adapt %p, MuxRequest %p, Status %8x\n", pAdapt, pMuxNdisRequest, Status)); } @@ -1208,7 +1208,7 @@ Return Value: { break; } - + MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState); if (GeneralStatus == NDIS_STATUS_LINK_STATE) @@ -1219,7 +1219,7 @@ Return Value: p != &pAdapt->VElanList; p = p->Flink) { - + pVElan = CONTAINING_RECORD(p, VELAN, Link); MUX_INCR_PENDING_RECEIVES(pVElan); @@ -1229,7 +1229,7 @@ Return Value: // if ((pVElan->MiniportInitPending) || (pVElan->MiniportHalting) || - (pVElan->MiniportAdapterHandle == NULL) || + (pVElan->MiniportAdapterHandle == NULL) || MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)) { MUX_DECR_PENDING_RECEIVES(pVElan); @@ -1237,7 +1237,7 @@ Return Value: { // // Keep track of the lastest status to indicated when VELAN power is on - // + // ASSERT(GeneralStatus == NDIS_STATUS_LINK_STATE); pVElan->LatestUnIndicateStatus = GeneralStatus; @@ -1247,12 +1247,12 @@ Return Value: pVElan->LatestUnIndicateLinkState = *(PNDIS_LINK_STATE)StatusIndication->StatusBuffer; } } - + continue; } // - // Save the last indicated status when + // Save the last indicated status when pVElan->LastIndicatedStatus = GeneralStatus; if (GeneralStatus == NDIS_STATUS_LINK_STATE) { @@ -1260,27 +1260,27 @@ Return Value: } // // Allocate a new status indication and set the destination handle to null to ensure that the status - // is indicated to protocols bound to mux velans. Copy only the fields that makes sense to pass up. For - // instance, do not copy PortNumber, RequestId, Flags, Guid, NdisReserved. Port Number is really not - // necessary to copy and pass up for the scenario because the port number is an entity that makes sense + // is indicated to protocols bound to mux velans. Copy only the fields that makes sense to pass up. For + // instance, do not copy PortNumber, RequestId, Flags, Guid, NdisReserved. Port Number is really not + // necessary to copy and pass up for the scenario because the port number is an entity that makes sense // between the protocol and the underlying miniport pair. - // - + // + NdisZeroMemory(&NewStatusIndication, sizeof(NDIS_STATUS_INDICATION)); - + NewStatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; NewStatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; NewStatusIndication.Header.Size = sizeof(NDIS_STATUS_INDICATION); - + NewStatusIndication.StatusCode = StatusIndication->StatusCode; NewStatusIndication.SourceHandle = pVElan->MiniportAdapterHandle; NewStatusIndication.DestinationHandle = NULL; - + NewStatusIndication.StatusBuffer = StatusIndication->StatusBuffer; NewStatusIndication.StatusBufferSize = StatusIndication->StatusBufferSize; NdisMIndicateStatusEx(pVElan->MiniportAdapterHandle, &NewStatusIndication); - + // // Mark this so that we forward a status complete // indication as well. @@ -1293,7 +1293,7 @@ Return Value: MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState); } while (FALSE); - + DBGPRINT(MUX_LOUD, ("<== PtStatus: Adapt %p, Status %x\n", pAdapt, GeneralStatus)); } @@ -1333,7 +1333,7 @@ Return Value: ETH_COMPARE_NETWORK_ADDRESSES_EQ(pVElan->McastAddrs[i], pDstMac, &AddrCompareResult); - + if (AddrCompareResult == 0) { break; @@ -1451,9 +1451,9 @@ Return Value: bPacketMatch = FALSE; } } - + DBGPRINT(MUX_VERY_LOUD, ("<== PtMatchPacketToVElan: VElan %p, PacketMatch %x\n", pVElan, bPacketMatch)); - + return (bPacketMatch); } @@ -1489,7 +1489,7 @@ Return Value: // // Store the new power state. // - + pAdapt->PtDevicePowerState = *(PNDIS_DEVICE_POWER_STATE)pNetPnPEventNotification->NetPnPEvent.Buffer; DBGPRINT(MUX_LOUD, ("==> PnPNetEventSetPower: Adapt %p, SetPower to %d\n", @@ -1531,7 +1531,7 @@ Return Value: // break; } - + DBGPRINT(MUX_INFO, ("SetPower: Adapt %p, waiting for pending IO to complete\n", pAdapt)); @@ -1563,23 +1563,23 @@ Return Value: pVElan->QueuedRequest = FALSE; NdisReleaseSpinLock(&pVElan->Lock); - + NdisAcquireSpinLock(&pAdapt->Lock); - + pAdapt->OutstandingRequests ++; - + if ((pAdapt->Flags & MUX_BINDING_CLOSING)== MUX_BINDING_CLOSING) { - NdisReleaseSpinLock(&pAdapt->Lock); - Status = NDIS_STATUS_CLOSING; + NdisReleaseSpinLock(&pAdapt->Lock); + Status = NDIS_STATUS_CLOSING; } else { - NdisReleaseSpinLock(&pAdapt->Lock); + NdisReleaseSpinLock(&pAdapt->Lock); Status = NdisOidRequest( pAdapt->BindingHandle, &pVElan->Request.Request); - } + } if (Status != NDIS_STATUS_PENDING) { PtRequestComplete(pAdapt, @@ -1598,7 +1598,7 @@ Return Value: DBGPRINT(MUX_LOUD, ("<== PnPNetEventSetPower: Adapt %p, SetPower to %d\n", pAdapt, pAdapt->PtDevicePowerState)); - + return (NDIS_STATUS_SUCCESS); } @@ -1633,7 +1633,7 @@ Return Value: PLIST_ENTRY p; NDIS_EVENT PauseEvent; - DBGPRINT(MUX_LOUD, ("==> PtPnPHandler: Adapt %p, NetPnPEvent %d\n", pAdapt, + DBGPRINT(MUX_LOUD, ("==> PtPnPHandler: Adapt %p, NetPnPEvent %d\n", pAdapt, pNetPnPEventNotification->NetPnPEvent.NetEvent)); switch (pNetPnPEventNotification->NetPnPEvent.NetEvent) @@ -1661,7 +1661,7 @@ Return Value: } MUX_RELEASE_MUTEX(&GlobalMutex); - + Status = NDIS_STATUS_SUCCESS; break; case NetEventIMReEnableDevice: @@ -1675,8 +1675,8 @@ Return Value: PtBootStrapVElans(pAdapt, pNetPnPEventNotification->NetPnPEvent.Buffer); } - - + + MUX_RELEASE_MUTEX(&GlobalMutex); Status = NDIS_STATUS_SUCCESS; @@ -1688,23 +1688,23 @@ Return Value: pAdapt->BindingState = MuxAdapterBindingPausing; ASSERT(pAdapt->PauseEvent == NULL); - + if (pAdapt->OutstandingSends != 0) { NdisInitializeEvent(&PauseEvent); - + pAdapt->PauseEvent = &PauseEvent; - + NdisReleaseSpinLock(&pAdapt->Lock); NdisWaitEvent(&PauseEvent, 0); - + NdisAcquireSpinLock(&pAdapt->Lock); } - + pAdapt->BindingState = MuxAdapterBindingPaused; NdisReleaseSpinLock(&pAdapt->Lock); - + Status = NDIS_STATUS_SUCCESS; break; @@ -1712,15 +1712,15 @@ Return Value: pAdapt->BindingState = MuxAdapterBindingRunning; Status = NDIS_STATUS_SUCCESS; break; - - + + default: Status = NDIS_STATUS_SUCCESS; break; } - DBGPRINT(MUX_LOUD, ("<== PtPnPHandler: Adapt %p, NetPnPEvent %d, Status %8x\n", pAdapt, + DBGPRINT(MUX_LOUD, ("<== PtPnPHandler: Adapt %p, NetPnPEvent %d, Status %8x\n", pAdapt, pNetPnPEventNotification->NetPnPEvent.NetEvent, Status)); return Status; } @@ -1742,12 +1742,12 @@ Routine Description: routines are protected by NDIS against pre-emption by UnbindAdapter. If this routine will be called from any other context, it should be protected against a simultaneous call to our UnbindAdapter handler. - + Arguments: pAdapt - Pointer to Adapter structure - pVElanKey - Points to a Unicode string naming the VELAN to create. - + pVElanKey - Points to a Unicode string naming the VELAN to create. + Return Value: NDIS_STATUS_SUCCESS if we either found a duplicate VELAN or @@ -1759,11 +1759,11 @@ Return Value: { NDIS_STATUS Status; PVELAN pVElan; - + Status = NDIS_STATUS_SUCCESS; pVElan = NULL; - DBGPRINT(MUX_LOUD, ("=> PtCreateAndStartVElan: Adapter %p, ElanKey %ws\n", + DBGPRINT(MUX_LOUD, ("=> PtCreateAndStartVElan: Adapter %p, ElanKey %ws\n", pAdapt, pVElanKey->Buffer)); do @@ -1788,9 +1788,9 @@ Return Value: break; } } - + pVElan = NULL; - + if (pVElanKey != NULL) { pVElan = PtAllocateAndInitializeVElan(pAdapt, pVElanKey); @@ -1824,9 +1824,9 @@ Return Value: pVElan = NULL; break; } - + PtDereferenceVElan(pVElan,(UCHAR*) "CreatVelan"); - + } while (FALSE); @@ -1871,7 +1871,7 @@ Return Value: do { Length = sizeof(VELAN) + pVElanKey->Length + sizeof(WCHAR); - + // // Allocate a VELAN data structure. // @@ -1890,27 +1890,27 @@ Return Value: NdisZeroMemory(pVElan, Length); NdisInitializeListHead(&pVElan->Link); NdisInitializeListHead(&pVElan->GlobalLink); - + // // Initialize the built-in request structure to signify // that it is used to forward NDIS requests. // pVElan->Request.pVElan = pVElan; NdisInitializeEvent(&pVElan->Request.Event); - + // // Store in the key name. // pVElan->CfgDeviceName.Length = 0; - pVElan->CfgDeviceName.Buffer = (PWCHAR)((PUCHAR)pVElan + - sizeof(VELAN)); - pVElan->CfgDeviceName.MaximumLength = + pVElan->CfgDeviceName.Buffer = (PWCHAR)((PUCHAR)pVElan + + sizeof(VELAN)); + pVElan->CfgDeviceName.MaximumLength = pVElanKey->Length + sizeof(WCHAR); (VOID)NdisUpcaseUnicodeString(&pVElan->CfgDeviceName, pVElanKey); pVElan->CfgDeviceName.Buffer[pVElanKey->Length/sizeof(WCHAR)] = ((WCHAR)0); - // + // // Initialize LastIndicatedStatus to media connect // pVElan->LastIndicatedStatus = NDIS_STATUS_LINK_STATE; @@ -1962,7 +1962,7 @@ Return Value: #ifdef IEEE_VLAN_SUPPORT // // Allocate lookaside list for tag headers. - // + // NdisInitializeNPagedLookasideList ( &pVElan->TagLookaside, NULL, @@ -1974,9 +1974,9 @@ Return Value: #endif // - // Finally link this VELAN to the Adapter's VELAN list. + // Finally link this VELAN to the Adapter's VELAN list. // - PtReferenceVElan(pVElan, (PUCHAR)"adapter"); + PtReferenceVElan(pVElan, (PUCHAR)"adapter"); MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState); @@ -1989,7 +1989,7 @@ Return Value: MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState); NdisAcquireSpinLock(&GlobalLock); - InsertTailList(&VElanList, &pVElan->GlobalLink); + InsertTailList(&VElanList, &pVElan->GlobalLink); NdisReleaseSpinLock(&GlobalLock);; } while (FALSE); @@ -2034,7 +2034,7 @@ Return Value: NdisFreeSpinLock(&pVElan->PauseLock); #ifdef IEEE_VLAN_SUPPORT - NdisDeleteNPagedLookasideList(&pVElan->TagLookaside); + NdisDeleteNPagedLookasideList(&pVElan->TagLookaside); #endif NdisFreeMemory(pVElan, 0, 0); @@ -2056,11 +2056,11 @@ Routine Description: ASSUMPTION: this is only called in the context of unbinding from the underlying miniport. If it may be called from elsewhere, this should protect itself from re-entrancy. - + Arguments: pVElan - Pointer to VELAN to be stopped. - + Return Value: None @@ -2151,16 +2151,16 @@ Return Value: } else { - if (bMiniportInitCancelled || + if (bMiniportInitCancelled || ((MiniportAdapterHandle == NULL) && !pVElan->MiniportHalting)) { - + // // No NDIS events can come to this VELAN since it // was never initialized as a miniport. We need to unlink // it explicitly here. // - PtUnlinkVElanFromAdapter(pVElan); + PtUnlinkVElanFromAdapter(pVElan); } } @@ -2177,18 +2177,18 @@ PtUnlinkVElanFromAdapter( Routine Description: Utility routine to unlink a VELAN from its parent ADAPT structure. - + Arguments: pVElan - Pointer to VELAN to be unlinked. - + Return Value: None --*/ { - PADAPT pAdapt = pVElan->pAdapt; + PADAPT pAdapt = pVElan->pAdapt; LOCK_STATE LockState; DBGPRINT(MUX_LOUD, ("==> PtUnlinkVElanFromAdapter: VELAN %p, Adapt %p\n", pVElan, pAdapt)); @@ -2198,7 +2198,7 @@ Return Value: // // Remove this VELAN from the global list // - + NdisAcquireSpinLock(&GlobalLock); RemoveEntryList(&pVElan->GlobalLink); NdisReleaseSpinLock(&GlobalLock); @@ -2210,7 +2210,7 @@ Return Value: RemoveEntryList(&pVElan->Link); pAdapt->VElanCount--; - + MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState); pVElan->pAdapt = NULL; PtDereferenceVElan(pVElan, (PUCHAR)"adapter"); @@ -2239,7 +2239,7 @@ Arguments: Return Value: Pointer to matching VELAN or NULL if not found. - + --*/ { PLIST_ENTRY p; @@ -2250,7 +2250,7 @@ Return Value: ASSERT_AT_PASSIVE(); - DBGPRINT(MUX_LOUD, ("==> PtFindElan: Adapter %p, ElanKey %ws\n", pAdapt, + DBGPRINT(MUX_LOUD, ("==> PtFindElan: Adapter %p, ElanKey %ws\n", pAdapt, pVElanKey->Buffer)); pVElan = NULL; @@ -2262,8 +2262,8 @@ Return Value: // // Make an up-cased copy of the given string. // - VElanKeyName.Buffer = NdisAllocateMemoryWithTagPriority(pAdapt->BindingHandle, - pVElanKey->MaximumLength, + VElanKeyName.Buffer = NdisAllocateMemoryWithTagPriority(pAdapt->BindingHandle, + pVElanKey->MaximumLength, MUX_TAG, LowPoolPriority); if (VElanKeyName.Buffer == NULL) @@ -2288,13 +2288,13 @@ Return Value: pVElan = CONTAINING_RECORD(p, VELAN, Link); if ((VElanKeyName.Length == pVElan->CfgDeviceName.Length) && - (memcmp(VElanKeyName.Buffer, pVElan->CfgDeviceName.Buffer, + (memcmp(VElanKeyName.Buffer, pVElan->CfgDeviceName.Buffer, VElanKeyName.Length) == 0)) { Found = TRUE; break; } - + p = p->Flink; } @@ -2314,7 +2314,7 @@ Return Value: NdisFreeMemory(VElanKeyName.Buffer, VElanKeyName.Length, 0); } - DBGPRINT(MUX_LOUD, ("<== PtFindElan: Adapter %p, ElanKey %ws, VElan %p\n", pAdapt, + DBGPRINT(MUX_LOUD, ("<== PtFindElan: Adapter %p, ElanKey %ws, VElan %p\n", pAdapt, pVElanKey->Buffer, pVElan)); return pVElan; } @@ -2324,7 +2324,7 @@ NDIS_STATUS PtBootStrapVElans( IN PADAPT pAdapt, IN PNDIS_STRING InstanceName OPTIONAL - + ) /*++ @@ -2348,7 +2348,7 @@ Return Value: NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings"); PWSTR buffer; LOCK_STATE LockState; - NDIS_CONFIGURATION_OBJECT ConfigObject; + NDIS_CONFIGURATION_OBJECT ConfigObject; DBGPRINT(MUX_LOUD, ("==> PtBootStrapElans: adapter %p\n", pAdapt)); // @@ -2356,7 +2356,7 @@ Return Value: // Status = NDIS_STATUS_SUCCESS; AdapterConfigHandle = NULL; - + do { DBGPRINT(MUX_LOUD, ("PtBootStrapElans: Starting ELANs on adapter %p\n", pAdapt)); @@ -2380,12 +2380,12 @@ Return Value: DBGPRINT(MUX_ERROR, ("PtBootStrapElans: OpenProtocolConfiguration failed\n")); Status = NDIS_STATUS_OPEN_FAILED; break; - } + } // // Read the "UpperBindings" reserved key that contains a list // of device names representing our miniport instances corresponding - // to this lower binding. The UpperBindings is a + // to this lower binding. The UpperBindings is a // MULTI_SZ containing a list of device names. We will loop through // this list and initialize the virtual miniports. // @@ -2408,7 +2408,7 @@ Return Value: while(*buffer != L'\0') { NDIS_STRING DeviceName; - + NdisInitUnicodeString(&DeviceName, buffer); if (InstanceName != NULL) @@ -2422,7 +2422,7 @@ Return Value: else { - Status = PtCreateAndStartVElan(pAdapt, &DeviceName); + Status = PtCreateAndStartVElan(pAdapt, &DeviceName); } if (NDIS_STATUS_SUCCESS != Status) { @@ -2431,19 +2431,19 @@ Return Value: } buffer = (PWSTR)((PUCHAR)buffer + DeviceName.Length + sizeof(WCHAR)); }; - + } while (FALSE); // // Close config handles - // + // if (NULL != AdapterConfigHandle) { NdisCloseConfiguration(AdapterConfigHandle); } // // If the driver cannot create any velan for the adapter - // + // if (Status != NDIS_STATUS_SUCCESS) { MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState); @@ -2455,10 +2455,10 @@ Return Value: Status = NDIS_STATUS_SUCCESS; } MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState); - } - + } + DBGPRINT(MUX_LOUD, ("<== PtBootStrapElans: adapter %p, Status %8x\n", pAdapt, Status)); - + return Status; } @@ -2484,7 +2484,7 @@ Return Value: --*/ { - + NdisInterlockedIncrement((PLONG)&pVElan->RefCount); #if !DBG @@ -2506,7 +2506,7 @@ PtDereferenceVElan( Routine Description: - Subtract a reference from an VElan structure. + Subtract a reference from an VElan structure. If the reference count becomes zero, deallocate it. Arguments: @@ -2534,13 +2534,13 @@ Return Value: { // // Free memory if there is no outstanding reference. - // Note: Length field is not required if the memory + // Note: Length field is not required if the memory // is allocated with NdisAllocateMemoryWithTagPriority. // PtDeallocateVElan(pVElan); } - - DBGPRINT(MUX_LOUD, ("DereferenceElan: VElan %p (%s) new count %d\n", + + DBGPRINT(MUX_LOUD, ("DereferenceElan: VElan %p (%s) new count %d\n", pVElan, String, rc)); return (rc); } @@ -2567,13 +2567,13 @@ Return Value: --*/ { - + #if !DBG UNREFERENCED_PARAMETER(String); #endif NdisInterlockedIncrement((PLONG)&pAdapt->RefCount); - + DBGPRINT(MUX_LOUD, ("ReferenceAdapter: Adapter %p (%s) new count %d\n", pAdapt, String, pAdapt->RefCount)); @@ -2589,7 +2589,7 @@ PtDereferenceAdapter( Routine Description: - Subtract a reference from an Adapter structure. + Subtract a reference from an Adapter structure. If the reference count becomes zero, deallocate it. Arguments: @@ -2618,20 +2618,20 @@ Return Value: { // // Free memory if there is no outstanding reference. - // Note: Length field is not required if the memory + // Note: Length field is not required if the memory // is allocated with NdisAllocateMemoryWithTagPriority. // NdisFreeMemory(pAdapt, 0, 0); } - DBGPRINT(MUX_LOUD, ("DereferenceAdapter: Adapter %p (%s) new count %d\n", + DBGPRINT(MUX_LOUD, ("DereferenceAdapter: Adapter %p (%s) new count %d\n", pAdapt, String, rc)); return (rc); } -VOID +VOID PtReceiveNBL( IN NDIS_HANDLE ProtocolBindingContext, IN PNET_BUFFER_LIST NetBufferLists, @@ -2642,7 +2642,7 @@ PtReceiveNBL( /*++ Routine Description: - ReceiveNetBufferList handler. + ReceiveNetBufferList handler. Arguments: ProtocolBindingContext Pointer to our PADAPT structure @@ -2673,12 +2673,12 @@ NOTE: This receive code path is not efficient, we will optimize it later. UCHAR Data[6]={0,0,0,0,0,0}; //BOOLEAN DispatchLevel; BOOLEAN bReturnNbl; - + #ifdef IEEE_VLAN_SUPPORT NDIS_STATUS NdisStatus; NDIS_NET_BUFFER_LIST_8021Q_INFO NdisPacket8021qInfo; BOOLEAN bAllocatedContext; - PRECV_NBL_ENTRY RecvContext; + PRECV_NBL_ENTRY RecvContext; #endif UNREFERENCED_PARAMETER(NumberOfNetBufferLists); @@ -2702,20 +2702,20 @@ NOTE: This receive code path is not efficient, we will optimize it later. // Return immediately if (pAdapt->PacketFilter == 0) - { + { if (NDIS_TEST_RECEIVE_CAN_PEND(ReceiveFlags) == TRUE) { NdisReturnNetBufferLists(pAdapt->BindingHandle, NetBufferLists, ReturnFlags); - } + } return; } while (NetBufferLists != NULL) { CurrentNetBufferList = NetBufferLists; - + NetBufferLists = NET_BUFFER_LIST_NEXT_NBL(NetBufferLists); NET_BUFFER_LIST_NEXT_NBL(CurrentNetBufferList) = NULL; @@ -2729,7 +2729,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. do { // Collect some information about the packet - pDstMac = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(CurrentNetBufferList), + pDstMac = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(CurrentNetBufferList), 6, (PVOID)Data, 1, @@ -2747,7 +2747,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. bIsBroadcast = ETH_IS_BROADCAST(pDstMac); #ifdef IEEE_VLAN_SUPPORT - // + // // Create Receive context to save information about tag // NdisStatus = NdisAllocateNetBufferListContext(CurrentNetBufferList, @@ -2761,8 +2761,8 @@ NOTE: This receive code path is not efficient, we will optimize it later. bAllocatedContext = TRUE; - RecvContext = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(CurrentNetBufferList); - NdisZeroMemory(RecvContext, sizeof(RECV_NBL_ENTRY)); + RecvContext = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(CurrentNetBufferList); + NdisZeroMemory(RecvContext, sizeof(RECV_NBL_ENTRY)); // // Strip off the VLAN Tag if present @@ -2772,7 +2772,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. // // If the VLAN tag is not present in the buffer, ignore this NBL // - DBGPRINT(MUX_LOUD,("PtReceiveNBL: NBL %p size < VLAN_TAG_HEADER_SIZE\n",CurrentNetBufferList)); + DBGPRINT(MUX_LOUD,("PtReceiveNBL: NBL %p size < VLAN_TAG_HEADER_SIZE\n",CurrentNetBufferList)); break; } @@ -2780,21 +2780,21 @@ NOTE: This receive code path is not efficient, we will optimize it later. { // // If the VLAN info is already in the NBL, take this information it - // - DBGPRINT(MUX_LOUD,("PtReceiveNBL: NBL %p already has Ieee8021QNetBufferListInfo\n",CurrentNetBufferList)); - - RtlCopyMemory((PVOID UNALIGNED) &NdisPacket8021qInfo, &NET_BUFFER_LIST_INFO(CurrentNetBufferList, Ieee8021QNetBufferListInfo),sizeof(NdisPacket8021qInfo)); + // + DBGPRINT(MUX_LOUD,("PtReceiveNBL: NBL %p already has Ieee8021QNetBufferListInfo\n",CurrentNetBufferList)); + + RtlCopyMemory((PVOID UNALIGNED) &NdisPacket8021qInfo, &NET_BUFFER_LIST_INFO(CurrentNetBufferList, Ieee8021QNetBufferListInfo),sizeof(NdisPacket8021qInfo)); } else { - NdisStatus = PtStripVlanTagNB(CurrentNetBufferList, &NdisPacket8021qInfo, RecvContext); + NdisStatus = PtStripVlanTagNB(CurrentNetBufferList, &NdisPacket8021qInfo, RecvContext); if (NdisStatus != NDIS_STATUS_SUCCESS) { break; } } -#endif +#endif // Lock down the VLAN list on the adapter so that no insertions // deletions to this list happen while we loop through it. The packet @@ -2833,7 +2833,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. MUX_DECR_PENDING_RECEIVES(pVElan); continue; } - + NdisAcquireSpinLock(&pVElan->PauseLock); if (!pVElan->Paused) @@ -2894,7 +2894,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. } else { - NdisReleaseSpinLock(&pVElan->PauseLock); + NdisReleaseSpinLock(&pVElan->PauseLock); MUX_DECR_PENDING_RECEIVES(pVElan); } @@ -2906,7 +2906,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. if (bReturnNbl == TRUE) { -#ifdef IEEE_VLAN_SUPPORT +#ifdef IEEE_VLAN_SUPPORT // // Free the context only if we are returning the NBL here. // Otherwise MPReturnNetBufferLists will free it. @@ -2914,9 +2914,9 @@ NOTE: This receive code path is not efficient, we will optimize it later. if (bAllocatedContext) { NdisFreeNetBufferListContext(CurrentNetBufferList, - sizeof(RECV_NBL_ENTRY)); + sizeof(RECV_NBL_ENTRY)); } -#endif +#endif // // The NetBufferList is not pending with any upper protocol. @@ -2933,7 +2933,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. { NET_BUFFER_LIST_NEXT_NBL(LastReturnNetBufferList) = CurrentNetBufferList; } - + LastReturnNetBufferList = CurrentNetBufferList; NET_BUFFER_LIST_NEXT_NBL(LastReturnNetBufferList) = NULL; } @@ -2958,7 +2958,7 @@ NOTE: This receive code path is not efficient, we will optimize it later. } -VOID +VOID PtSendNBLComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNET_BUFFER_LIST NetBufferLists, @@ -2996,7 +2996,7 @@ Return Value: ProtocolBindingContext,NetBufferLists)); DispatchLevel = NDIS_TEST_SEND_COMPLETE_AT_DISPATCH_LEVEL(SendCompleteFlags); - + while(NetBufferLists) { CurrentNetBufferList = NetBufferLists; @@ -3019,12 +3019,12 @@ Return Value: sizeof(IM_NBL_ENTRY)); #ifdef IEEE_VLAN_SUPPORT - + if ((Flags & MUX_RETREAT_DATA) != 0) { - MPRestoreSendNBL(pVElan, - CurrentNetBufferList, - NULL, + MPRestoreSendNBL(pVElan, + CurrentNetBufferList, + NULL, MdlAllocatedNetBuffers); } @@ -3043,7 +3043,7 @@ Return Value: CurrentNetBufferList, SendCompleteFlags); - + MUX_DECR_PENDING_SENDS(pVElan); MUX_ACQUIRE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); @@ -3056,14 +3056,14 @@ Return Value: } MUX_RELEASE_SPIN_LOCK(&pAdapt->Lock, DispatchLevel); - + } DBGPRINT(MUX_VERY_LOUD,("<== PtSendNBLComplete: ProtocolBindingContext %p, NetBufferLists %p\n",ProtocolBindingContext,NetBufferLists)); } #ifdef IEEE_VLAN_SUPPORT -NDIS_STATUS +NDIS_STATUS PtHandleReceiveTaggingNB( IN PVELAN pVElan, IN PNET_BUFFER_LIST NetBufferList, @@ -3081,7 +3081,7 @@ Routine Description: Arguments: pVElan Pointer to the VELAN structure NetBufferList Pointer to the indicated packet from the lower miniport - NdisPacket8021qInfo 802.1Q tag information + NdisPacket8021qInfo 802.1Q tag information Return Value: NDIS_STATUS_SUCCESS @@ -3101,9 +3101,9 @@ Return Value: DBGPRINT(MUX_VERY_LOUD,("==> PtHandleReceiveTaggingNB: VElan %p, NetBufferList %p, NdisPacket8021qInfo %p\n",pVElan,NetBufferList, NdisPacket8021qInfo)); do { - RecvContext = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferList); - RecvContext->Flags = 0; - + RecvContext = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferList); + RecvContext->Flags = 0; + // // If the vlan ID of the virtual miniport is 0, the miniport should // act like it doesn't support VELAN tag processing @@ -3144,7 +3144,7 @@ Return Value: MUX_INCR_STATISTICS(&pVElan->RcvVlanIdErrors); break; - } + } Storage=NULL; pFrame = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(NetBufferList), 2 * ETH_LENGTH_OF_ADDRESS + VLAN_TAG_HEADER_SIZE, @@ -3158,9 +3158,9 @@ Return Value: Status = NDIS_STATUS_INVALID_PACKET; break; } - + pTpid = (USHORT UNALIGNED *)((PUCHAR)pFrame + 2 * ETH_LENGTH_OF_ADDRESS); - + // //Strip header only if it's present in the packet // @@ -3175,8 +3175,8 @@ Return Value: RtlMoveMemory(pDst, pFrame, 2 * ETH_LENGTH_OF_ADDRESS); - NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = NdisPacket8021qInfo->Value; - + NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = NdisPacket8021qInfo->Value; + NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(NetBufferList), VLAN_TAG_HEADER_SIZE, FALSE, @@ -3189,7 +3189,7 @@ Return Value: return Status; } -NDIS_STATUS +NDIS_STATUS PtStripVlanTagNB( IN PNET_BUFFER_LIST NetBufferList, OUT PNDIS_NET_BUFFER_LIST_8021Q_INFO NdisPacket8021qInfo, @@ -3218,7 +3218,7 @@ Return Value: PVOID pFrame = NULL; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PVOID Storage; - + DBGPRINT(MUX_VERY_LOUD,("==> PtStripVlanTagNB: NetBufferList %p, NdisPacket8021qInfo %p\n",NetBufferList, NdisPacket8021qInfo)); do @@ -3254,14 +3254,14 @@ Return Value: COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(*NdisPacket8021qInfo, pTagHeader); RtlCopyMemory((PVOID UNALIGNED) &RecvContext->TagHeader, pTagHeader, 2); - + } while(FALSE); DBGPRINT(MUX_VERY_LOUD,("<== PtStripVlanTagNB: NetBufferList %p, NdisPacket8021qInfo %p, Status %8x\n",NetBufferList, NdisPacket8021qInfo, Status)); return Status; } -NDIS_STATUS +NDIS_STATUS PtRestoreReceiveNBL( IN PNET_BUFFER_LIST NetBufferList ) @@ -3288,7 +3288,7 @@ Return Value: do { - ReceiveNblEntry = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferList); + ReceiveNblEntry = (PRECV_NBL_ENTRY) NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferList); // // Check ifthe NBL was modified @@ -3297,7 +3297,7 @@ Return Value: { break; } - + // // Retreat the net buffer list // @@ -3310,10 +3310,10 @@ Return Value: { break; } - + // // Find the start address of the frame - // + // Storage=NULL; pFrame = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(NetBufferList), 2 * ETH_LENGTH_OF_ADDRESS + VLAN_TAG_HEADER_SIZE, @@ -3325,7 +3325,7 @@ Return Value: { ASSERT(0); Status = NDIS_STATUS_INVALID_PACKET; - break; + break; } // @@ -3333,13 +3333,13 @@ Return Value: // original state // Tpid = TPID; - + NdisMoveMemory(pFrame, pFrame + VLAN_TAG_HEADER_SIZE, (2 * ETH_LENGTH_OF_ADDRESS)); - + NdisMoveMemory(pFrame + (2 * ETH_LENGTH_OF_ADDRESS), &Tpid, 2); - + NdisMoveMemory(pFrame + (2 * ETH_LENGTH_OF_ADDRESS) + sizeof(Tpid), &ReceiveNblEntry->TagHeader, 2); - + NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = 0; } while (FALSE); diff --git a/network/ndis/mux/driver/60/public.h b/network/ndis/mux/driver/60/public.h index 972939c7..ddf13b24 100644 --- a/network/ndis/mux/driver/60/public.h +++ b/network/ndis/mux/driver/60/public.h @@ -12,7 +12,7 @@ Abstract: Author: - + Environment: user and kernel diff --git a/network/ndis/mux/notifyob/adapter.cpp b/network/ndis/mux/notifyob/adapter.cpp index a208aa57..99bfe6e8 100644 --- a/network/ndis/mux/notifyob/adapter.cpp +++ b/network/ndis/mux/notifyob/adapter.cpp @@ -114,7 +114,7 @@ CMuxPhysicalAdapter::~CMuxPhysicalAdapter (VOID) // // Function: CMuxPhysicalAdapter::LoadConfiguration // -// Purpose: Read the registry to get the device IDs of the +// Purpose: Read the registry to get the device IDs of the // virtual miniports installed on the adapter and // crate an instance to represent each virtual miniport. // @@ -142,7 +142,7 @@ HRESULT CMuxPhysicalAdapter::LoadConfiguration (VOID) TraceMsg( L"-->CMuxPhysicalAdapter::LoadConfiguration.\n" ); // - // Build the registry key using the adapter guid under which + // Build the registry key using the adapter guid under which // device IDs of the virtual miniports are stored. // @@ -159,7 +159,7 @@ HRESULT CMuxPhysicalAdapter::LoadConfiguration (VOID) L"%s\\%s", c_szAdapterList, szAdapterGuid ); - + szAdapterGuidKey[MAX_PATH]='\0'; lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE, szAdapterGuidKey, @@ -211,14 +211,14 @@ HRESULT CMuxPhysicalAdapter::LoadConfiguration (VOID) if ( lResult == ERROR_SUCCESS ) { lpMiniport = lpMiniportList; - + #ifndef PASSTHRU_NOTIFY // // In case of mux, c_szUpperBindings is a REG_MULTI_SZ string. // - + lpMiniport[dwBytes-1] = '\0'; while ( wcslen(lpMiniport) ) { @@ -510,14 +510,14 @@ HRESULT CMuxPhysicalAdapter::Remove (VOID) // // Arguments: // IN eApplyAction: Action that was last performed. -// +// // // Returns: S_OK. // // Notes: // More than one action could have been performed by the user // but this function is called only once at the end. So, the argument -// only denotes the very last action performed. For example, if the +// only denotes the very last action performed. For example, if the // user deletes one miniport and adds two miniports then, the argument // will denote an add action. // @@ -705,14 +705,14 @@ HRESULT CMuxPhysicalAdapter::ApplyRegistryChanges (ConfigAction eApplyAction) // Arguments: // IN pfCallback : SendPnpConfig Callback interface. // IN eApplyAction: Action that was last performed. -// +// // // Returns: S_OK. // // Notes: // More than one action could have been performed by the user // but this function is called only once at the end. So, the argument -// only denotes the very last action performed. For example, if the +// only denotes the very last action performed. For example, if the // user deletes one miniport and adds two miniports then, the argument // will denote an add action. // @@ -727,7 +727,7 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( DWORD i; HRESULT hr; -#ifdef CUSTOM_EVENTS +#ifdef CUSTOM_EVENTS LPWSTR lpDevice; WCHAR szMiniportGuid[MAX_PATH+1]; DWORD dwBytes; @@ -739,7 +739,7 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( UNREFERENCED_PARAMETER(eApplyAction); TraceMsg( L"-->CMuxPhysicalAdapter::ApplyPnpChanges.\n" ); -#ifdef CUSTOM_EVENTS +#ifdef CUSTOM_EVENTS // // Find the instance of the adapter to get its bindname. @@ -767,7 +767,7 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( hr ); } -#endif +#endif dwMiniportCount = m_MiniportsToAdd.ListCount(); @@ -848,7 +848,7 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( } free( lpDevice ); } -#endif +#endif } dwMiniportCount = m_MiniportsToRemove.ListCount(); @@ -935,11 +935,11 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( free( lpDevice ); } } -#endif +#endif } -#ifdef CUSTOM_EVENTS +#ifdef CUSTOM_EVENTS CoTaskMemFree( lpszBindName ); #endif @@ -956,7 +956,7 @@ HRESULT CMuxPhysicalAdapter::ApplyPnpChanges( // Purpose: Cancel any changes made. // // Arguments: None -// +// // // Returns: S_OK. // @@ -980,7 +980,7 @@ HRESULT CMuxPhysicalAdapter::CancelChanges (VOID) // Purpose: Find out if there is no miniport installed on the adapter. // // Arguments: None -// +// // // Returns: TRUE if all the miniports associated with this adapter have been // uninstalled and there is none pending to be added, otherwise FALSE. diff --git a/network/ndis/mux/notifyob/common.cpp b/network/ndis/mux/notifyob/common.cpp index 5ca2ca7f..671d08f5 100644 --- a/network/ndis/mux/notifyob/common.cpp +++ b/network/ndis/mux/notifyob/common.cpp @@ -103,8 +103,8 @@ void DumpBindingPath (INetCfgBindingPath *pncbp) IEnumNetCfgBindingInterface *pencbi; INetCfgBindingInterface *pncbi; DWORD dwIndex; - ULONG ulCount; -#endif + ULONG ulCount; +#endif hr = pncbp->GetPathToken( &lpsz ); @@ -190,9 +190,9 @@ void DumpBindingPath (INetCfgBindingPath *pncbp) else { TraceMsg( L" EnumBindingInterfaces failed, (HRESULT = %x)\n", - hr ); + hr ); } -#endif +#endif return; } @@ -203,7 +203,7 @@ void DumpComponent (INetCfgComponent *pncc) ULONG ulStatus; HRESULT hr; hr = pncc->GetDisplayName( &lpsz ); - + if ( hr == S_OK ) { TraceMsg( L" \t\tComponent: %s\n", @@ -393,7 +393,7 @@ HRESULT HrFindInstance (INetCfg *pnc, *ppnccMiniport = pncc; } } - } + } ReleaseObj( pencc ); } @@ -552,14 +552,14 @@ DeleteFromMultiSzValue ( lpCurrentValueTemp[dwLen-1]='\0'; while( wcslen(lpCurrentValueTemp) > 0) { - //if a register in the existing register sequence do not match szMiniportGuid, copy to new register sequence + //if a register in the existing register sequence do not match szMiniportGuid, copy to new register sequence if ( _wcsicmp(lpCurrentValueTemp, szMiniportGuid) != 0 ) { StringCchCopyW ( lpNewValueTemp, wcslen(lpCurrentValueTemp), //size of the register lpCurrentValueTemp ); - + *(lpNewValueTemp+=wcslen(lpCurrentValueTemp)+1)='\0'; - + lpNewValueTemp += wcslen(lpNewValueTemp) + 1; dwNewLen += (DWORD)wcslen(lpNewValueTemp) + 1; } @@ -605,7 +605,7 @@ AddDevicePrefix ( LPWSTR lpNewStr; size_t cchNewStr = wcslen(lpStr) + wcslen(c_szDevicePrefix) + 1; - lpNewStr = (LPWSTR)malloc( cchNewStr * sizeof(WCHAR) ); + lpNewStr = (LPWSTR)malloc( cchNewStr * sizeof(WCHAR) ); if ( lpNewStr ) { StringCchCopyW (lpNewStr, diff --git a/network/ndis/mux/notifyob/common.h b/network/ndis/mux/notifyob/common.h index 517641f7..4e6896ca 100644 --- a/network/ndis/mux/notifyob/common.h +++ b/network/ndis/mux/notifyob/common.h @@ -27,14 +27,14 @@ enum ConfigAction { - eActUnknown, - eActInstall, - eActAdd, + eActUnknown, + eActInstall, + eActAdd, eActRemove, eActUpdate, eActPropertyUIAdd, eActPropertyUIRemove -}; +}; // // PnP ID, also referred to as Hardware ID, of the protocol interface. diff --git a/network/ndis/mux/notifyob/dllmain.cpp b/network/ndis/mux/notifyob/dllmain.cpp index 636f2c8a..e91c1d74 100644 --- a/network/ndis/mux/notifyob/dllmain.cpp +++ b/network/ndis/mux/notifyob/dllmain.cpp @@ -80,7 +80,7 @@ STDAPI DllCanUnloadNow(void) TraceMsg( L"-->DllCanUnloadNow(HRESULT = %x).\n", hr ); - return hr; + return hr; } ///////////////////////////////////////////////////////////////////////////// diff --git a/network/ndis/mux/notifyob/list.h b/network/ndis/mux/notifyob/list.h index b52b75e7..0ba64b45 100644 --- a/network/ndis/mux/notifyob/list.h +++ b/network/ndis/mux/notifyob/list.h @@ -5,7 +5,7 @@ // // File: LIST . H // -// Contents: +// Contents: // // Notes: List manipulation functions. // @@ -20,7 +20,7 @@ #include <windows.h> -template<class X, class Y> class List { +template<class X, class Y> class List { struct Node { X item; Y key; @@ -107,7 +107,7 @@ template<class X, class Y> HRESULT List<X, Y>::Remove (X *item) return S_OK; } - + template<class X, class Y> HRESULT List<X, Y>::RemoveThis (X item) { Node *temp; diff --git a/network/ndis/mux/notifyob/notify.RC b/network/ndis/mux/notifyob/notify.RC index 4888e305..78a8eb95 100644 --- a/network/ndis/mux/notifyob/notify.RC +++ b/network/ndis/mux/notifyob/notify.RC @@ -19,7 +19,7 @@ FONT 8, "MS Shell Dlg" BEGIN CONTROL "Remove a Miniport",IDC_REMOVE,"Button", BS_AUTORADIOBUTTON | WS_TABSTOP,39,73,75,10 - CONTROL "Add a Miniport",IDC_ADD,"Button",BS_AUTORADIOBUTTON | + CONTROL "Add a Miniport",IDC_ADD,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,39,36,61,10 LTEXT "Removal of miniport happens in FIFO order",IDC_STATIC, 39,93,135,8 diff --git a/network/ndis/mux/notifyob/notify.cpp b/network/ndis/mux/notifyob/notify.cpp index 3d0a55ff..542e12e1 100644 --- a/network/ndis/mux/notifyob/notify.cpp +++ b/network/ndis/mux/notifyob/notify.cpp @@ -6,7 +6,7 @@ // File: N O T I F Y . C P P // // Contents: Sample notify object code -// +// // Notes: // // Author: Alok Sinha @@ -103,10 +103,10 @@ CMuxNotify::~CMuxNotify (VOID) // //---------------------------------------------------------------------------- -// INetCfgComponentControl -// +// INetCfgComponentControl +// // The following functions provide the INetCfgComponentControl interface. -// +// //---------------------------------------------------------------------------- // @@ -125,7 +125,7 @@ CMuxNotify::~CMuxNotify (VOID) // STDMETHODIMP CMuxNotify::Initialize (INetCfgComponent* pncc, - INetCfg* pnc, + INetCfg* pnc, BOOL fInstalling) { HRESULT hr = S_OK; @@ -150,7 +150,7 @@ STDMETHODIMP CMuxNotify::Initialize (INetCfgComponent* pncc, // - // If this not an installation, then we need to + // If this not an installation, then we need to // initialize all of our data and classes // @@ -222,7 +222,7 @@ STDMETHODIMP CMuxNotify::ApplyRegistryChanges(VOID) m_AdaptersToAdd.Find( i, &pAdapter ); - + pAdapter->ApplyRegistryChanges( eActAdd ); } @@ -240,7 +240,7 @@ STDMETHODIMP CMuxNotify::ApplyRegistryChanges(VOID) m_AdaptersToRemove.Find( i, &pAdapter ); - + pAdapter->ApplyRegistryChanges( eActRemove ); } @@ -276,7 +276,7 @@ STDMETHODIMP CMuxNotify::ApplyRegistryChanges(VOID) // // Returns: S_OK. // -// Notes: +// Notes: STDMETHODIMP CMuxNotify::ApplyPnpChanges ( INetCfgPnpReconfigCallback* pfCallback) @@ -353,10 +353,10 @@ STDMETHODIMP CMuxNotify::ApplyPnpChanges ( //---------------------------------------------------------------------------- -// INetCfgComponentSetup -// +// INetCfgComponentSetup +// // The following functions provide the INetCfgComponentSetup interface. -// +// //---------------------------------------------------------------------------- // ---------------------------------------------------------------------- @@ -445,7 +445,7 @@ STDMETHODIMP CMuxNotify::ReadAnswerFile (PCWSTR pszAnswerFile, UNREFERENCED_PARAMETER(pszAnswerFile); UNREFERENCED_PARAMETER(pszAnswerSection); - + TraceMsg( L"-->CMuxNotify INetCfgSetup::ReadAnswerFile.\n" ); // We will pretend here that szParamReadFromAnswerFile was actually @@ -498,20 +498,20 @@ STDMETHODIMP CMuxNotify::Removing (VOID) //---------------------------------------------------------------------------- -// INetCfgComponentNotifyBinding -// +// INetCfgComponentNotifyBinding +// // The following functions provide the INetCfgComponentNotifyBinding interface. -// +// //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // // Function: CMuxNotify::QueryBindingPath // -// Purpose: This is specific to the component being installed. This will +// Purpose: This is specific to the component being installed. This will // ask us if we want to bind to the Item being passed into // this routine. We can disable the binding by returning -// NETCFG_S_DISABLE_QUERY +// NETCFG_S_DISABLE_QUERY // // // Arguments: @@ -522,7 +522,7 @@ STDMETHODIMP CMuxNotify::Removing (VOID) // // Notes: // -STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag, +STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag, IN INetCfgBindingPath *pncbp) { UNREFERENCED_PARAMETER(pncbp); @@ -543,7 +543,7 @@ STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag, // // Function: CMuxNotify::NotifyBindingPath // -// Purpose: We are now being told to bind to the component passed to us. +// Purpose: We are now being told to bind to the component passed to us. // // // Arguments: @@ -557,7 +557,7 @@ STDMETHODIMP CMuxNotify::QueryBindingPath (IN DWORD dwChangeFlag, -STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, +STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, IN INetCfgBindingPath *pncbp) { INetCfgComponent *pnccLower; @@ -608,7 +608,7 @@ STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, // // We are interested only in binding to a // physical ethernet adapters. - // + // if ( dwCharcteristics & NCF_PHYSICAL ) { @@ -631,7 +631,7 @@ STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, m_eApplyAction = eActRemove; } } - } // Physical Adapters. + } // Physical Adapters. else if (dwCharcteristics & NCF_VIRTUAL) { } @@ -651,7 +651,7 @@ STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, } // Got the upper and lower components. - } + } TraceMsg( L"<--CMuxNotify INetCfgNotifyBinding::NotifyBindingPath(HRESULT = %x).\n", S_OK ); @@ -664,9 +664,9 @@ STDMETHODIMP CMuxNotify::NotifyBindingPath (IN DWORD dwChangeFlag, //---------------------------------------------------------------------------- // INetCfgComponentNotifyGlobal -// +// // The following functions provide the INetCfgComponentNotifyGlobal interface. -// +// //---------------------------------------------------------------------------- // ---------------------------------------------------------------------- @@ -749,9 +749,9 @@ STDMETHODIMP CMuxNotify::SysQueryBindingPath (DWORD dwChangeFlag, if ( hr == S_OK ) { // - // We are interested only in bindings to physical + // We are interested only in bindings to physical // ethernet adapters. - // + // if ( dwCharcteristics & NCF_PHYSICAL ) { @@ -774,7 +774,7 @@ STDMETHODIMP CMuxNotify::SysQueryBindingPath (DWORD dwChangeFlag, } #endif - } // Physical Adapters. + } // Physical Adapters. else { if (dwCharcteristics & NCF_VIRTUAL) { @@ -784,7 +784,7 @@ STDMETHODIMP CMuxNotify::SysQueryBindingPath (DWORD dwChangeFlag, if ( !_wcsicmp(pszwInfIdLower, c_szMuxMiniport) && !_wcsicmp(pszwInfIdUpper, c_szMuxProtocol) ) { - + TraceMsg( L" Disabling the binding between %s " L"and %s.\n", pszwInfIdUpper, @@ -886,10 +886,10 @@ STDMETHODIMP CMuxNotify::SysNotifyComponent (DWORD dwChangeFlag, //---------------------------------------------------------------------------- -// INetCfgComponentPropertyUi -// +// INetCfgComponentPropertyUi +// // The following functions provide the INetCfgComponentPropertyUi interface. -// +// //---------------------------------------------------------------------------- // ---------------------------------------------------------------------- @@ -1034,7 +1034,7 @@ STDMETHODIMP CMuxNotify::CancelProperties (VOID) // // Returns: S_OK on success, otherwise an error code // -// Notes: +// Notes: // STDMETHODIMP CMuxNotify::ApplyProperties (VOID) { @@ -1118,7 +1118,7 @@ STDMETHODIMP CMuxNotify::QueryPropertyUi (IUnknown * pUnk) reinterpret_cast<PVOID *>(&pLanConnUiInfo)); ReleaseObj( pLanConnUiInfo ); - } + } #endif TraceMsg(L"<--CMuxNotify INetCfgPropertyUi::QueryPropertyUi(HRESULT = %x).\n", @@ -1133,7 +1133,7 @@ STDMETHODIMP CMuxNotify::QueryPropertyUi (IUnknown * pUnk) // // Purpose: Save the LAN connection context. // -// Arguments: +// Arguments: // IN pUnk: Pointer to IUnknown. // // Returns: S_OK on success, otherwise an error code @@ -1169,7 +1169,7 @@ STDMETHODIMP CMuxNotify::SetContext (IUnknown * pUnk) // // Function: CMuxNotify::HrLoadAdapterConfiguration // -// Purpose: This loads the Miniport and adapters that have already been +// Purpose: This loads the Miniport and adapters that have already been // installed into our own data structures // // Arguments: None. @@ -1209,7 +1209,7 @@ HRESULT CMuxNotify::HrLoadAdapterConfiguration (VOID) // // If dwDisp indicates that a new key is created then, we know there // is no adapter currently listed underneath and we simply - // return, otherwise, we enumerate the subkeys, each one representing an + // return, otherwise, we enumerate the subkeys, each one representing an // adapter. // @@ -1299,7 +1299,7 @@ HRESULT CMuxNotify::HrLoadAdapterConfiguration (VOID) // Purpose: Get the upper and lower component of the first interface // of a binding path. // -// Arguments: +// Arguments: // IN pncbp : Binding path. // OUT ppnccUpper: Upper component. // OUT ppnccLower: Lower component. @@ -1327,7 +1327,7 @@ HRESULT CMuxNotify::HrGetUpperAndLower (INetCfgBindingPath* pncbp, hr = pncbp->EnumBindingInterfaces(&pencbi); if (S_OK == hr) { - + // // get the first binding interface // @@ -1368,7 +1368,7 @@ HRESULT CMuxNotify::HrGetUpperAndLower (INetCfgBindingPath* pncbp, // Purpose: Create an instance representing the physical adapter and install // a virtual miniport. // -// Arguments: +// Arguments: // IN pnccAdapter: Pointer to the physical adapter. // // Returns: S_OK, or an error. @@ -1411,7 +1411,7 @@ HRESULT CMuxNotify::HrAddAdapter (INetCfgComponent *pnccAdapter) else { hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); } - } + } TraceMsg( L"<--CMuxNotify::HrAddAdapter(HRESULT = %x).\n", hr ); @@ -1426,7 +1426,7 @@ HRESULT CMuxNotify::HrAddAdapter (INetCfgComponent *pnccAdapter) // Purpose: Deletes the instance representing the physical adapter // and uninstalls all the virtual miniports. // -// Arguments: +// Arguments: // IN pnccAdapter: Pointer to the physical adapter. // // Returns: S_OK, or an error. @@ -1453,7 +1453,7 @@ HRESULT CMuxNotify::HrRemoveAdapter (INetCfgComponent *pnccAdapter) if ( hr == S_OK ) { - m_AdaptersToRemove.Insert( pAdapter, + m_AdaptersToRemove.Insert( pAdapter, guidAdapter ); hr = pAdapter->Remove(); @@ -1463,7 +1463,7 @@ HRESULT CMuxNotify::HrRemoveAdapter (INetCfgComponent *pnccAdapter) // Restore the bindings of other protocols to the physical // adapter. // - + EnableBindings( pnccAdapter, TRUE ); #endif @@ -1482,14 +1482,14 @@ HRESULT CMuxNotify::HrRemoveAdapter (INetCfgComponent *pnccAdapter) // // Purpose: Installs a virtual miniport. // -// Arguments: +// Arguments: // IN pAdapter : Pointer to the physical adapter class instance. // IN pguidAdapter: Pointer to the GUID of the adapter. // // Returns: S_OK, or an error. // // -// Notes: +// Notes: // HRESULT CMuxNotify::HrAddMiniport (CMuxPhysicalAdapter *pAdapter, @@ -1502,15 +1502,15 @@ HRESULT CMuxNotify::HrAddMiniport (CMuxPhysicalAdapter *pAdapter, TraceMsg( L"-->CMuxNotify::HrAddMiniport.\n" ); // - // Limit the number of virtual miniports + // Limit the number of virtual miniports // if ((pAdapter->MiniportCount() + pAdapter->MiniportAddCount()) >= MAX_VIRTUAL_MP_PER_ADAPTER) { - hr = HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES ); + hr = HRESULT_FROM_WIN32( ERROR_NO_SYSTEM_RESOURCES ); TraceMsg( L" Virtual miniport limit reached\n" ); } - if ( hr == S_OK ) + if ( hr == S_OK ) { #pragma prefast(suppress:8197, "The instance is freed in the destructor") pMiniport = new CMuxVirtualMiniport( m_pnc, @@ -1578,14 +1578,14 @@ HRESULT CMuxNotify::HrAddMiniport (CMuxPhysicalAdapter *pAdapter, // // Purpose: Uninstalls a virtual miniport. // -// Arguments: +// Arguments: // IN pAdapter : Pointer to the physical adapter class instance. // IN pguidAdapter: Pointer to the GUID of the adapter. // // Returns: S_OK, or an error. // // -// Notes: +// Notes: // HRESULT CMuxNotify::HrRemoveMiniport (CMuxPhysicalAdapter *pAdapter, @@ -1673,7 +1673,7 @@ LRESULT CMuxNotify::OnOk (IN HWND hWndPage) if ( ::SendMessage(GetDlgItem(hWndPage, IDC_ADD), BM_GETCHECK, 0, 0) == BST_CHECKED ) { - + m_eApplyAction = eActPropertyUIAdd; } else { @@ -1785,7 +1785,7 @@ INT_PTR CALLBACK NotifyDialogProc (HWND hWnd, LPNMHDR pnmh = (LPNMHDR)lParam; switch (pnmh->code) { - + case PSN_KILLACTIVE: // @@ -1851,7 +1851,7 @@ UINT CALLBACK NotifyPropSheetPageProc(HWND hWnd, // // Function: CMuxNotify::EnableBindings // -// Purpose: Enable/Disable the bindings of other protocols to +// Purpose: Enable/Disable the bindings of other protocols to // the physical adapter. // // Arguments: @@ -1869,7 +1869,7 @@ VOID CMuxNotify::EnableBindings (INetCfgComponent *pnccAdapter, IEnumNetCfgBindingPath *pencbp; INetCfgBindingPath *pncbp; HRESULT hr; - + TraceMsg( L"-->CMuxNotify::EnableBindings.\n" ); diff --git a/network/ndis/mux/notifyob/notify.h b/network/ndis/mux/notifyob/notify.h index 08f16e00..4d5cc936 100644 --- a/network/ndis/mux/notifyob/notify.h +++ b/network/ndis/mux/notifyob/notify.h @@ -43,7 +43,7 @@ class CMuxNotify : // Must inherit from CComObjectRoot(Ex) for reference count // management and default threading model. // - + public CComObjectRoot, // @@ -185,7 +185,7 @@ class CMuxNotify : STDMETHOD (SysNotifyBindingPath) ( IN DWORD dwChangeFlag, IN INetCfgBindingPath* pncbp); - + STDMETHOD (SysNotifyComponent) ( IN DWORD dwChangeFlag, IN INetCfgComponent* pncc); diff --git a/network/ndis/mux/notifyob/notifyn.idl b/network/ndis/mux/notifyob/notifyn.idl index 319ddbfd..bcdd6b67 100644 --- a/network/ndis/mux/notifyob/notifyn.idl +++ b/network/ndis/mux/notifyob/notifyn.idl @@ -5,7 +5,7 @@ // // File: NOTIFYN.IDL // -// Contents: +// Contents: // // Notes: // diff --git a/network/ndis/mux/notifyob/public.h b/network/ndis/mux/notifyob/public.h index 3d6147fc..25be17d5 100644 --- a/network/ndis/mux/notifyob/public.h +++ b/network/ndis/mux/notifyob/public.h @@ -12,7 +12,7 @@ Abstract: Author: - + Environment: user and kernel diff --git a/network/ndis/mux/notifyob/virtual.cpp b/network/ndis/mux/notifyob/virtual.cpp index fd3cce0e..da5c1690 100644 --- a/network/ndis/mux/notifyob/virtual.cpp +++ b/network/ndis/mux/notifyob/virtual.cpp @@ -173,10 +173,10 @@ HRESULT CMuxVirtualMiniport::Install (VOID) INetCfgComponent *pnccMiniport; HRESULT hr; LPWSTR *pmszwRefs=NULL; - OBO_TOKEN *pOboToken=NULL; + OBO_TOKEN *pOboToken=NULL; DWORD dwSetupFlags=0; LPCWSTR pszwAnswerFile=NULL; - LPCWSTR pszwAnswerSections=NULL; + LPCWSTR pszwAnswerSections=NULL; TraceMsg( L"-->CMuxVirtualMiniport::Install.\n" ); @@ -189,7 +189,7 @@ HRESULT CMuxVirtualMiniport::Install (VOID) hr = pncClass->QueryInterface( IID_INetCfgClassSetup, (void **)&pncClassSetup ); if ( hr == S_OK ) { - + hr = pncClassSetup->Install( c_szMuxMiniport, pOboToken, dwSetupFlags, @@ -205,7 +205,7 @@ HRESULT CMuxVirtualMiniport::Install (VOID) TraceMsg( L" Failed to get the instance guid, uninstalling " L" the miniport.\n" ); - + pncClassSetup->DeInstall( pnccMiniport, pOboToken, pmszwRefs ); @@ -278,7 +278,7 @@ HRESULT CMuxVirtualMiniport::DeInstall (VOID) if ( hr == S_OK ) { TraceMsg( L" Found the miniport instance to uninstall.\n" ); - + hr = pncClassSetup->DeInstall( pnccMiniport, pOboToken, pmszwRefs ); @@ -351,7 +351,7 @@ HRESULT CMuxVirtualMiniport::ApplyRegistryChanges(ConfigAction eApplyAction) L"%s\\%s", c_szAdapterList, szAdapterGuid ); - + szAdapterGuidKey[MAX_PATH]='\0'; lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE, szAdapterGuidKey, @@ -509,7 +509,7 @@ HRESULT CMuxVirtualMiniport::ApplyRegistryChanges(ConfigAction eApplyAction) // // Function: CMuxVirtualMiniport::ApplyPnpChanges // -// Purpose: +// Purpose: // // Arguments: // IN eApplyAction: Action performed. diff --git a/network/ndis/mux/notifyob/virtual.h b/network/ndis/mux/notifyob/virtual.h index 5cb8f050..dd31ea74 100644 --- a/network/ndis/mux/notifyob/virtual.h +++ b/network/ndis/mux/notifyob/virtual.h @@ -48,7 +48,7 @@ class CMuxVirtualMiniport GUID *guidAdapter); virtual ~CMuxVirtualMiniport(VOID); - + HRESULT LoadConfiguration(VOID); VOID GetAdapterGUID (GUID *); diff --git a/network/ndis/ndisprot/6x/sys/60/ndisprot60.rc b/network/ndis/ndisprot/6x/sys/60/ndisprot60.rc index 59a37c53..5e9c282c 100644 --- a/network/ndis/ndisprot/6x/sys/60/ndisprot60.rc +++ b/network/ndis/ndisprot/6x/sys/60/ndisprot60.rc @@ -9,8 +9,8 @@ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: - ndisprot.rc - + ndisprot60.rc + Abstract: Internal resource file for driver. diff --git a/network/ndis/ndisprot/6x/sys/630/ndisprot630.rc b/network/ndis/ndisprot/6x/sys/630/ndisprot630.rc index f50de3f9..91bff7f3 100644 --- a/network/ndis/ndisprot/6x/sys/630/ndisprot630.rc +++ b/network/ndis/ndisprot/6x/sys/630/ndisprot630.rc @@ -9,8 +9,8 @@ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: - ndisprot.rc - + ndisprot630.rc + Abstract: Internal resource file for driver. diff --git a/network/ndis/ndisprot/6x/sys/debug.c b/network/ndis/ndisprot/6x/sys/debug.c index 40e90984..db2c389c 100644 --- a/network/ndis/ndisprot/6x/sys/debug.c +++ b/network/ndis/ndisprot/6x/sys/debug.c @@ -43,7 +43,7 @@ ndisprotAuditAllocMem( ) { PVOID pBuffer; - PNPROTD_ALLOCATION pAllocInfo; + PNPROTD_ALLOCATION pAllocInfo = NULL; if (!ndisprotdInitDone) { @@ -88,7 +88,7 @@ ndisprotAuditAllocMem( ndisprotdMemoryTail->Next = pAllocInfo; } ndisprotdMemoryTail = pAllocInfo; - + ndisprotdAllocCount++; NdisReleaseSpinLock(&(ndisprotdMemoryLock)); } @@ -295,9 +295,9 @@ ndisprotFreeDbgLock( VOID ) { - + ASSERT(ndisprotdSpinLockInitDone == 1); - + ndisprotdSpinLockInitDone = 0; NdisFreeSpinLock(&(ndisprotdLockLock)); } diff --git a/network/ndis/ndisprot/6x/sys/debug.h b/network/ndis/ndisprot/6x/sys/debug.h index 64de3453..89c35907 100644 --- a/network/ndis/ndisprot/6x/sys/debug.h +++ b/network/ndis/ndisprot/6x/sys/debug.h @@ -80,7 +80,7 @@ ndisprotReleaseSpinLock( IN ULONG LineNumber ); -extern +extern VOID ndisprotFreeDbgLock( VOID diff --git a/network/ndis/ndisprot/6x/sys/excallbk.c b/network/ndis/ndisprot/6x/sys/excallbk.c index baa2298c..48ec71b7 100644 --- a/network/ndis/ndisprot/6x/sys/excallbk.c +++ b/network/ndis/ndisprot/6x/sys/excallbk.c @@ -12,7 +12,7 @@ Module Name: ExCallbk.c Abstract: The routines in this module helps to solve driver load order - dependency between this sample and NDISWDM sample. These + dependency between this sample and NDISWDM sample. These routines are not required in a typical protocol driver. By default this module is not included in the sample. You include these routines by adding EX_CALLBACK defines to the 'sources' file. Read the @@ -52,7 +52,7 @@ typedef VOID (* NOTIFY_PRESENCE_CALLBACK)(OUT PVOID Source); #endif // ALLOC_PRAGMA -BOOLEAN +BOOLEAN ndisprotRegisterExCallBack() { OBJECT_ATTRIBUTES ObjectAttr; @@ -63,9 +63,9 @@ ndisprotRegisterExCallBack() DEBUGP(DL_LOUD, ("--> ndisprotRegisterExCallBack\n")); PAGED_CODE(); - + do { - + RtlInitUnicodeString(&CallBackObjectName, NDISPROT_CALLBACK_NAME); InitializeObjectAttributes(&ObjectAttr, @@ -73,13 +73,13 @@ ndisprotRegisterExCallBack() OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); - + Status = ExCreateCallback(&CallbackObject, &ObjectAttr, TRUE, TRUE); - + if (!NT_SUCCESS(Status)) { @@ -87,7 +87,7 @@ ndisprotRegisterExCallBack() bResult = FALSE; break; } - + CallbackRegisterationHandle = ExRegisterCallback(CallbackObject, ndisprotCallback, (PVOID)NULL); @@ -101,8 +101,8 @@ ndisprotRegisterExCallBack() ExNotifyCallback(CallbackObject, (PVOID)CALLBACK_SOURCE_NDISPROT, (PVOID)NULL); - - + + }while(FALSE); if(!bResult) { @@ -116,16 +116,16 @@ ndisprotRegisterExCallBack() { ObDereferenceObject(CallbackObject); CallbackObject = NULL; - } + } } DEBUGP(DL_LOUD, ("<-- ndisprotRegisterExCallBack\n")); return bResult; - + } -VOID +VOID ndisprotUnregisterExCallBack() { DEBUGP(DL_LOUD, ("--> ndisprotUnregisterExCallBack\n")); @@ -142,10 +142,10 @@ ndisprotUnregisterExCallBack() { ObDereferenceObject(CallbackObject); CallbackObject = NULL; - } - + } + DEBUGP(DL_LOUD, ("<-- ndisprotUnregisterExCallBack\n")); - + } VOID @@ -156,40 +156,40 @@ ndisprotCallback( ) { NOTIFY_PRESENCE_CALLBACK func; - - DEBUGP(DL_LOUD, ("==>ndisprotoCallback: Source %lx, CallbackAddr %p\n", + + DEBUGP(DL_LOUD, ("==>ndisprotoCallback: Source %lx, CallbackAddr %p\n", Source, CallbackAddr)); - + // // if we are the one issuing this notification, just return // - if (Source == CALLBACK_SOURCE_NDISPROT) { + if (Source == CALLBACK_SOURCE_NDISPROT) { return; } - + // // Notification is coming from NDISWDM // let it know that you are here // ASSERT(Source == (PVOID)CALLBACK_SOURCE_NDISWDM); - + if(Source == (PVOID)CALLBACK_SOURCE_NDISWDM) { ASSERT(CallbackAddr); - + if (CallbackAddr == NULL) { DEBUGP(DL_ERROR, ("Callback called with invalid address %p\n", CallbackAddr)); - return; + return; } func = CallbackAddr; - + func(CALLBACK_SOURCE_NDISPROT); } - + DEBUGP(DL_LOUD, ("<==ndisprotoCallback: Source, %lx\n", Source)); - + } #endif diff --git a/network/ndis/ndisprot/6x/sys/macros.h b/network/ndis/ndisprot/6x/sys/macros.h index d750129c..59ddc18d 100644 --- a/network/ndis/ndisprot/6x/sys/macros.h +++ b/network/ndis/ndisprot/6x/sys/macros.h @@ -76,7 +76,7 @@ Revision History: NdisReleaseSpinLock(_pLock); \ } \ } - + #define NPROT_FREE_LOCK(_pLock) NdisFreeSpinLock(_pLock) #define NPROT_FREE_DBG_LOCK() @@ -94,17 +94,17 @@ Revision History: #define NPROT_REMOVE_HEAD_LIST(_pList) RemoveHeadList(_pList) - + #define NPROT_RCV_NBL_TO_LIST_ENTRY(_pNbl) \ (&((PNPROT_RECV_NBL_RSVD)(NET_BUFFER_LIST_PROTOCOL_RESERVED(_pNbl)))->Link) #define NPROT_RCV_NBL_FROM_LIST_ENTRY(_pEnt) \ (((PNPROT_RECV_NBL_RSVD)(CONTAINING_RECORD(_pEnt, NPROT_RECV_NBL_RSVD, Link)))->pNetBufferList) - + // // Send net buffer list context -// +// #define NPROT_IRP_FROM_SEND_NBL(_pNbl) \ (((PNPROT_SEND_NETBUFLIST_RSVD)((_pNbl)->Context->ContextData + (_pNbl)->Context->Offset))->pIrp) @@ -128,7 +128,7 @@ Revision History: // Cancel IDs are generated by using the partial cancel ID we got from // NDIS ORed with a monotonically increasing locally generated ID. // -#define NPROT_CANCEL_ID_LOW_MASK (((ULONG_PTR)-1) >> 8) +#define NPROT_CANCEL_ID_LOW_MASK (((ULONG_PTR)-1) >> 8) #define NPROT_GET_NEXT_CANCEL_ID() \ (PVOID)(Globals.PartialCancelId | \ @@ -188,7 +188,7 @@ Revision History: #define NPROT_TEST_FLAGS(_FlagsVar, _Mask, _BitsToCheck) \ (((_FlagsVar) & (_Mask)) == (_BitsToCheck)) - + #define NDIS_STATUS_TO_NT_STATUS(_NdisStatus, _pNtStatus) \ { \ diff --git a/network/ndis/ndisprot/6x/sys/ndisbind.c b/network/ndis/ndisprot/6x/sys/ndisbind.c index 5257d3a2..7ad3c4d5 100644 --- a/network/ndis/ndisprot/6x/sys/ndisbind.c +++ b/network/ndis/ndisprot/6x/sys/ndisbind.c @@ -70,11 +70,11 @@ Return Value: --*/ { - PNDISPROT_OPEN_CONTEXT pOpenContext; + PNDISPROT_OPEN_CONTEXT pOpenContext = NULL; NDIS_STATUS Status; UNREFERENCED_PARAMETER(ProtocolDriverContext); - + do { // @@ -120,12 +120,12 @@ Return Value: pOpenContext->State = NdisprotInitializing; // - // Here we reference the open context to make sure that even if + // Here we reference the open context to make sure that even if // ndisprotCreateBinding failed, open context is still valid - // + // NPROT_REF_OPEN(pOpenContext); // - // Set up the NDIS binding, ndisprotCreateBinding does the cleanup for the + // Set up the NDIS binding, ndisprotCreateBinding does the cleanup for the // binding if somehow it fails to create the binding, the // Status = ndisprotCreateBinding( @@ -134,21 +134,21 @@ Return Value: BindContext, (PUCHAR)BindParameters->AdapterName->Buffer, BindParameters->AdapterName->Length); - - + + if (Status != NDIS_STATUS_SUCCESS) { // // Dereference the open context because we referenced it before we call // ndisprotCreateBinding - // + // NPROT_DEREF_OPEN(pOpenContext); break; } // // Dereference the open context because we referenced it before we call // ndisprotCreateBinding - // + // NPROT_DEREF_OPEN(pOpenContext); } while (FALSE); @@ -216,7 +216,7 @@ Return Value: PNDISPROT_OPEN_CONTEXT pOpenContext; UNREFERENCED_PARAMETER(UnbindContext); - + pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; NPROT_STRUCT_ASSERT(pOpenContext, oc); @@ -272,7 +272,7 @@ Return Value: NPROT_SIGNAL_EVENT(&pOpenContext->BindEvent); } - + NDIS_STATUS NdisprotPnPEventHandler( IN NDIS_HANDLE ProtocolBindingContext, @@ -308,7 +308,7 @@ Return Value: switch (pNetPnPEventNotification->NetPnPEvent.NetEvent) { - case NetEventSetPower: + case NetEventSetPower: NPROT_STRUCT_ASSERT(pOpenContext, oc); pOpenContext->PowerState = *(PNET_DEVICE_POWER_STATE)pNetPnPEventNotification->NetPnPEvent.Buffer; @@ -359,14 +359,14 @@ Return Value: // // Wait all sends to be complete. // - + NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); pOpenContext->State = NdisprotPausing; // // we could also complete the PnP Event asynchrously. // - while (TRUE) + while (TRUE) { if (pOpenContext->PendedSendCount == 0) break; @@ -379,19 +379,19 @@ Return Value: NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); } - + NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); // // Return all queued receives. // ndisprotFlushReceiveQueue(pOpenContext); pOpenContext->State = NdisprotPaused; - + break; case NetEventRestart: - + ASSERT(pOpenContext->State == NdisprotPaused); // // Get the updated attributes @@ -403,7 +403,7 @@ Return Value: break; } BufferLength = pNetPnPEventNotification->NetPnPEvent.BufferLength; - + ASSERT(BufferLength == sizeof(NDIS_PROTOCOL_RESTART_PARAMETERS)); RestartParameters = (PNDIS_PROTOCOL_RESTART_PARAMETERS)Buffer; @@ -412,7 +412,7 @@ Return Value: pOpenContext->State = NdisprotRunning; break; - + case NetEventQueryRemoveDevice: case NetEventCancelRemoveDevice: case NetEventReconfigure: @@ -431,7 +431,7 @@ Return Value: return (Status); } - + VOID NdisprotProtocolUnloadHandler( VOID @@ -500,7 +500,7 @@ Return Value: NET_FRAME_TYPE FrameTypeArray[2] = {NDIS_ETH_TYPE_802_1X, NDIS_ETH_TYPE_802_1Q}; #if DBG PNDISPROT_OPEN_CONTEXT pTmpOpenContext; -#endif +#endif DEBUGP(DL_LOUD, ("CreateBinding: open %p/%x, device [%s]\n", pOpenContext, pOpenContext->Flags, pBindingInfo)); @@ -512,7 +512,7 @@ Return Value: // // Check if we already have a binding to this device. // -#if DBG +#if DBG pTmpOpenContext = ndisprotLookupDevice(pBindingInfo, BindingInfoLength); ASSERT(pTmpOpenContext == NULL); @@ -527,7 +527,7 @@ Return Value: Status = NDIS_STATUS_FAILURE; break; } -#endif +#endif NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); @@ -548,10 +548,10 @@ Return Value: } NPROT_COPY_MEM(pOpenContext->DeviceName.Buffer, pBindingInfo, BindingInfoLength); -#pragma prefast(suppress: 12009, "DeviceName length will not cause overflow") +#pragma prefast(suppress: 12009, "DeviceName length will not cause overflow") *(PWCHAR)((PUCHAR)pOpenContext->DeviceName.Buffer + BindingInfoLength) = L'\0'; NdisInitUnicodeString(&pOpenContext->DeviceName, pOpenContext->DeviceName.Buffer); - + NdisZeroMemory(&PoolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS)); PoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; @@ -561,39 +561,39 @@ Return Value: PoolParameters.ContextSize = sizeof(NPROT_SEND_NETBUFLIST_RSVD); PoolParameters.fAllocateNetBuffer = TRUE; PoolParameters.PoolTag = NPROT_ALLOC_TAG; - + pOpenContext->SendNetBufferListPool = NdisAllocateNetBufferListPool( Globals.NdisProtocolHandle, - &PoolParameters); + &PoolParameters); if (pOpenContext->SendNetBufferListPool == NULL) { DEBUGP(DL_WARN, ("CreateBinding: failed to alloc" " send net buffer list pool\n")); - + Status = NDIS_STATUS_RESOURCES; break; } - PoolParameters.ContextSize = 0; - + PoolParameters.ContextSize = 0; + pOpenContext->RecvNetBufferListPool = NdisAllocateNetBufferListPool( Globals.NdisProtocolHandle, &PoolParameters); - + if (pOpenContext->RecvNetBufferListPool == NULL) { DEBUGP(DL_WARN, ("CreateBinding: failed to alloc" " recv net buffer list pool.\n")); - + Status = NDIS_STATUS_RESOURCES; break; } - + // // Assume that the device is powered up. // pOpenContext->PowerState = NetDeviceStateD0; - + // // Open the adapter. // @@ -614,8 +614,8 @@ Return Value: NDIS_DECLARE_PROTOCOL_OPEN_CONTEXT(NDISPROT_OPEN_CONTEXT); Status = NdisOpenAdapterEx(Globals.NdisProtocolHandle, (NDIS_HANDLE)pOpenContext, - &OpenParameters, - BindContext, + &OpenParameters, + BindContext, &pOpenContext->BindingHandle); if (Status == NDIS_STATUS_PENDING) @@ -651,18 +651,18 @@ Return Value: // Get MAC options. // pOpenContext->MacOptions = BindParameters->MacOptions; - - + + // // Get the max frame size. // pOpenContext->MaxFrameSize = BindParameters->MtuSize; - + // // Get the media connect status. // GenericUlong = BindParameters->MediaConnectState; - + if (GenericUlong == NdisMediaStateConnected) { NPROT_SET_FLAGS(pOpenContext->Flags, NPROTO_MEDIA_FLAGS, NPROTO_MEDIA_CONNECTED); @@ -772,7 +772,7 @@ Return Value: { ASSERT(pOpenContext->ClosingEvent == NULL); pOpenContext->ClosingEvent = NULL; - + NPROT_SET_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_CLOSING); if (pOpenContext->PendedSendCount != 0) @@ -780,7 +780,7 @@ Return Value: pOpenContext->ClosingEvent = &ClosingEvent; NPROT_INIT_EVENT(&ClosingEvent); } - + DoCloseBinding = TRUE; } @@ -790,10 +790,10 @@ Return Value: { ULONG PacketFilter = 0; ULONG BytesRead = 0; - + // // Set Packet filter to 0 before closing the binding - // + // Status = ndisprotDoRequest( pOpenContext, NDIS_DEFAULT_PORT_NUMBER, @@ -807,10 +807,10 @@ Return Value: { DEBUGP(DL_WARN, ("ShutDownBinding: set packet filter failed: %x\n", Status)); } - + // // Set multicast list to null before closing the binding - // + // Status = ndisprotDoRequest( pOpenContext, NDIS_DEFAULT_PORT_NUMBER, @@ -856,7 +856,7 @@ Return Value: NPROT_ASSERT(Status == NDIS_STATUS_SUCCESS); pOpenContext->BindingHandle = NULL; - + NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); NPROT_SET_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_IDLE); @@ -867,7 +867,7 @@ Return Value: } } while (FALSE); - + // // Remove it from the global list. @@ -977,7 +977,7 @@ Return Value: pOpenContext, pOpenContext->PendedSendCount)); NPROT_WAIT_EVENT(pOpenContext->ClosingEvent, 0); - + } if (DoCancelReads) @@ -1024,7 +1024,7 @@ Return Value: { NDIS_HANDLE ProtocolHandle; - DEBUGP(DL_INFO, ("ProtocolUnload: ProtocolHandle %lp\n", + DEBUGP(DL_INFO, ("ProtocolUnload: ProtocolHandle %lp\n", Globals.NdisProtocolHandle)); if (Globals.NdisProtocolHandle != NULL) @@ -1037,7 +1037,7 @@ Return Value: } } - + NDIS_STATUS ndisprotDoRequest( IN PNDISPROT_OPEN_CONTEXT pOpenContext, @@ -1115,7 +1115,7 @@ Return Value: pNdisRequest->RequestId = NPROT_GET_NEXT_CANCEL_ID(); Status = NdisOidRequest(pOpenContext->BindingHandle, pNdisRequest); - + if (Status == NDIS_STATUS_PENDING) { @@ -1129,9 +1129,9 @@ Return Value: *pBytesProcessed = (RequestType == NdisRequestQueryInformation)? pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten: pNdisRequest->DATA.SET_INFORMATION.BytesRead; - + // - // The driver below should set the correct value to BytesWritten + // The driver below should set the correct value to BytesWritten // or BytesRead. But now, we just truncate the value to InformationBufferLength // if (*pBytesProcessed > InformationBufferLength) @@ -1188,7 +1188,7 @@ Return Value: Status = NDIS_STATUS_INVALID_DATA; break; } - + NPROT_STRUCT_ASSERT(pOpenContext, oc); NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); @@ -1244,8 +1244,8 @@ Return Value: { Status = NDIS_STATUS_ADAPTER_NOT_READY; } - - NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); + + NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); // // Let go of the binding. // @@ -1345,8 +1345,8 @@ Return Value: PNDISPROT_OPEN_CONTEXT pOpenContext; NDIS_STATUS GeneralStatus; PNDIS_LINK_STATE LinkState; - - + + pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; NPROT_STRUCT_ASSERT(pOpenContext, oc); @@ -1360,7 +1360,7 @@ Return Value: } GeneralStatus = StatusIndication->StatusCode; - + DEBUGP(DL_INFO, ("Status: Open %p, Status %x\n", pOpenContext, GeneralStatus)); @@ -1378,7 +1378,7 @@ Return Value: // // We continue and make note of status indications // - + // // NOTE that any actions we take based on these // status indications should take into account @@ -1389,7 +1389,7 @@ Return Value: switch(GeneralStatus) { case NDIS_STATUS_RESET_START: - + NPROT_ASSERT(!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_RESET_FLAGS, NPROTO_RESET_IN_PROGRESS)); @@ -1405,7 +1405,7 @@ Return Value: NPROT_ASSERT(NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_RESET_FLAGS, NPROTO_RESET_IN_PROGRESS)); - + NPROT_SET_FLAGS(pOpenContext->Flags, NPROTO_RESET_FLAGS, NPROTO_NOT_RESETTING); @@ -1413,9 +1413,9 @@ Return Value: break; case NDIS_STATUS_LINK_STATE: - + ASSERT(StatusIndication->StatusBufferSize >= sizeof(NDIS_LINK_STATE)); - + LinkState = (PNDIS_LINK_STATE)StatusIndication->StatusBuffer; if (LinkState->MediaConnectState == MediaConnectStateConnected) @@ -1430,15 +1430,15 @@ Return Value: NPROTO_MEDIA_FLAGS, NPROTO_MEDIA_DISCONNECTED); } - - break; - + + break; + default: break; } } while (FALSE); - + NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); } @@ -1571,7 +1571,7 @@ Return Value: // DEBUGP(DL_INFO, ("QueryBinding: found open %p\n", pOpenContext)); - + pQueryBinding->DeviceNameOffset = 0; pQueryBinding->DeviceNameLength = pOpenContext->DeviceName.Length; pQueryBinding->DeviceDescrOffset = 0; @@ -1615,7 +1615,7 @@ Return Value: NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); break; } - + pQueryBinding->DeviceDescrOffset = DeviceDescrOffset; *pBytesReturned += StringBytesWritten; @@ -1798,7 +1798,7 @@ Return Value: pOpenContext, pOpenContext->Flags, Oid, Status)); return (Status); - + } NDIS_STATUS @@ -1846,7 +1846,7 @@ Return Value: // // We should check the OID is settable by the user mode apps - // + // if (!ndisprotValidOid(Oid)) { DEBUGP(DL_WARN, ("SetOid: Oid %x cannot be set\n", Oid)); @@ -1854,7 +1854,7 @@ Return Value: Status = NDIS_STATUS_INVALID_DATA; break; } - + NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE)) @@ -1912,7 +1912,7 @@ Return Value: BOOLEAN ndisprotValidOid( - IN NDIS_OID Oid + IN NDIS_OID Oid ) /*++ @@ -1923,7 +1923,7 @@ Routine Description: Arguments: Oid - The OID which the user tries to set. - + Return Value: TRUE if the OID is allowed to set @@ -1943,7 +1943,7 @@ Return Value: break; } } - + return (i < NumOids); } @@ -1965,13 +1965,13 @@ Arguments: pOpenContext - pointer to open context RestartParameters - pointer to ndis restart parameters - + Return Value: None NOTE: Protocols should query any attribute: - 1. the attribute is not included in the RestartAttributes + 1. the attribute is not included in the RestartAttributes and 2. The protocol cares about whether the attributes is changed by underlying driver. --*/ @@ -1986,30 +1986,30 @@ NOTE: Protocols should query any attribute: WCHAR FilterNameBuffer[NPROT_MAX_FILTER_NAME_LENGTH]; PNDIS_RESTART_ATTRIBUTES NdisRestartAttributes; PNDIS_RESTART_GENERAL_ATTRIBUTES NdisGeneralAttributes; - + DEBUGP(DL_LOUD, ("ndisprotRestart: Open %p", pOpenContext)); // // Check the filter stack changes // if (RestartParameters->FilterModuleNameBuffer != NULL) { - + Buffer = RestartParameters->FilterModuleNameBuffer; - + while (RestartParameters->FilterModuleNameBufferLength > TotalLength) { - + BufferLength = *(PUSHORT)Buffer; - + TotalLength += BufferLength + sizeof(USHORT); Length = BufferLength + sizeof(USHORT); - + if (BufferLength >= (NPROT_MAX_FILTER_NAME_LENGTH * sizeof(WCHAR))) { BufferLength = (NPROT_MAX_FILTER_NAME_LENGTH - 1) * sizeof(WCHAR); } NdisMoveMemory(FilterNameBuffer, Buffer + sizeof(USHORT), BufferLength); - + BufferLength /= sizeof(WCHAR); // @@ -2020,17 +2020,17 @@ NOTE: Protocols should query any attribute: { FilterNameBuffer[BufferLength] = 0; } - + DEBUGP(DL_INFO, ("Filter: %ws\n", FilterNameBuffer)); - + Buffer += Length; } } // // Checked for updated attributes - // + // NdisRestartAttributes = RestartParameters->RestartAttributes; - + // // NdisProt is only interested in the generic attributes. // @@ -2042,20 +2042,20 @@ NOTE: Protocols should query any attribute: } NdisRestartAttributes = NdisRestartAttributes->Next; } - + // // Pick up the new attributes of interest // if (NdisRestartAttributes != NULL) { NdisGeneralAttributes = (PNDIS_RESTART_GENERAL_ATTRIBUTES)NdisRestartAttributes->Data; - + pOpenContext->MacOptions = NdisGeneralAttributes->MacOptions; pOpenContext->MaxFrameSize = NdisGeneralAttributes->MtuSize; - } - + } + DEBUGP(DL_LOUD, ("ndisprotRestart: Open %p", pOpenContext)); - + } - + diff --git a/network/ndis/ndisprot/6x/sys/ndisprot.h b/network/ndis/ndisprot/6x/sys/ndisprot.h index b4efbaf4..e497c89f 100644 --- a/network/ndis/ndisprot/6x/sys/ndisprot.h +++ b/network/ndis/ndisprot/6x/sys/ndisprot.h @@ -121,10 +121,10 @@ typedef struct _NDISPROT_OPEN_CONTEXT PFILE_OBJECT pFileObject; // Set on OPEN_DEVICE NDIS_HANDLE BindingHandle; - NDIS_HANDLE SendNetBufferListPool; + NDIS_HANDLE SendNetBufferListPool; // let every net buffer list contain one net buffer(don't know how many net buffers can be include in one list. NDIS_HANDLE RecvNetBufferListPool; - + ULONG MacOptions; ULONG MaxFrameSize; ULONG DataBackFillSize; @@ -148,12 +148,12 @@ typedef struct _NDISPROT_OPEN_CONTEXT ULONG oc_sig; // Signature for sanity NDISPROT_OPEN_STATE State; - PNPROT_EVENT ClosingEvent; + PNPROT_EVENT ClosingEvent; UCHAR CurrentAddress[NPROT_MAC_ADDR_LEN]; UCHAR MCastAddress[MAX_MULTICAST_ADDRESS][NPROT_MAC_ADDR_LEN]; } NDISPROT_OPEN_CONTEXT, *PNDISPROT_OPEN_CONTEXT; - + #define oc_signature 'OiuN' // diff --git a/network/ndis/ndisprot/6x/sys/ntdisp.c b/network/ndis/ndisprot/6x/sys/ntdisp.c index 21ceeaeb..c212f57d 100644 --- a/network/ndis/ndisprot/6x/sys/ntdisp.c +++ b/network/ndis/ndisprot/6x/sys/ntdisp.c @@ -61,12 +61,12 @@ Arguments: Return Value: NT Status code - + --*/ { NDIS_PROTOCOL_DRIVER_CHARACTERISTICS protocolChar = {0}; NTSTATUS status = STATUS_SUCCESS; - NDIS_STRING protoName = NDIS_STRING_CONST("NDISPROT"); + NDIS_STRING protoName = NDIS_STRING_CONST("NDISPROT"); UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; BOOLEAN fSymbolicLink = FALSE; @@ -74,7 +74,7 @@ Return Value: NDIS_HANDLE ProtocolDriverContext={0}; UNREFERENCED_PARAMETER(pRegistryPath); - + DEBUGP(DL_LOUD, ("DriverEntry\n")); Globals.pDriverObject = pDriverObject; @@ -96,7 +96,7 @@ Return Value: FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject); - + if (!NT_SUCCESS (status)) { // @@ -117,7 +117,7 @@ Return Value: } fSymbolicLink = TRUE; - + deviceObject->Flags |= DO_DIRECT_IO; Globals.ControlDeviceObject = deviceObject; @@ -126,7 +126,7 @@ Return Value: // // Initialize the protocol characterstic structure - // + // #if (NDIS_SUPPORT_NDIS630) {C_ASSERT(sizeof(protocolChar) >= NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2);} protocolChar.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS, @@ -159,7 +159,7 @@ Return Value: // // Register as a protocol driver // - + status = NdisRegisterProtocolDriver(ProtocolDriverContext, // driver context &protocolChar, &Globals.NdisProtocolHandle); @@ -190,16 +190,16 @@ Return Value: pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisprotCleanup; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisprotIoControl; - + pDriverObject->DriverUnload = NdisprotUnload; status = STATUS_SUCCESS; - + } while (FALSE); - + if (!NT_SUCCESS(status)) { @@ -216,14 +216,14 @@ Return Value: IoDeleteSymbolicLink(&win32DeviceName); fSymbolicLink = FALSE; } - + if (Globals.NdisProtocolHandle) { NdisDeregisterProtocolDriver(Globals.NdisProtocolHandle); Globals.NdisProtocolHandle = NULL; - } + } } - + return status; } @@ -252,7 +252,7 @@ Return Value: UNICODE_STRING win32DeviceName; PAGED_CODE(); UNREFERENCED_PARAMETER(DriverObject); - + DEBUGP(DL_LOUD, ("Unload Enter\n")); // @@ -261,7 +261,7 @@ Return Value: // RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); - IoDeleteSymbolicLink(&win32DeviceName); + IoDeleteSymbolicLink(&win32DeviceName); if (Globals.ControlDeviceObject) @@ -310,7 +310,7 @@ Return Value: NTSTATUS NtStatus = STATUS_SUCCESS; PAGED_CODE(); UNREFERENCED_PARAMETER(pDeviceObject); - + pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pIrpSp->FileObject->FsContext = NULL; @@ -352,7 +352,7 @@ Return Value: PNDISPROT_OPEN_CONTEXT pOpenContext; PAGED_CODE(); UNREFERENCED_PARAMETER(pDeviceObject); - + pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pOpenContext = pIrpSp->FileObject->FsContext; @@ -378,7 +378,7 @@ Return Value: return NtStatus; } - + NTSTATUS NdisprotCleanup( @@ -410,9 +410,9 @@ Return Value: ULONG PacketFilter; ULONG BytesProcessed; - + UNREFERENCED_PARAMETER(pDeviceObject); - + pIrpSp = IoGetCurrentIrpStackLocation(pIrp); pOpenContext = pIrpSp->FileObject->FsContext; @@ -437,7 +437,7 @@ Return Value: &BytesProcessed, FALSE // Don't wait for device to be powered on ); - + if (NdisStatus != NDIS_STATUS_SUCCESS) { DEBUGP(DL_INFO, ("Cleanup: Open %p, set packet filter (%x) failed: %x\n", @@ -449,7 +449,7 @@ Return Value: // NdisStatus = NDIS_STATUS_SUCCESS; } - + // // Mark this endpoint. // @@ -533,7 +533,7 @@ Return Value: // If we don't get this event in 5 seconds, time out. // NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED); - + if (NPROT_WAIT_EVENT(&Globals.BindsComplete, 5000)) { NtStatus = STATUS_SUCCESS; @@ -546,9 +546,9 @@ Return Value: break; case IOCTL_NDISPROT_QUERY_BINDING: - + NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED); - + Status = ndisprotQueryBinding( pIrp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.InputBufferLength, @@ -636,7 +636,7 @@ Return Value: NtStatus = STATUS_DEVICE_NOT_CONNECTED; } break; - + default: NtStatus = STATUS_NOT_SUPPORTED; @@ -715,9 +715,9 @@ Return Value: NPROT_ASSERT(pOpenContext->pFileObject != NULL); DEBUGP(DL_WARN, ("ndisprotOpenDevice: Open %p/%x already associated" - " with another FileObject %p\n", + " with another FileObject %p\n", pOpenContext, pOpenContext->Flags, pOpenContext->pFileObject)); - + NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); NPROT_DEREF_OPEN(pOpenContext); // ndisprotOpenDevice failure @@ -729,17 +729,17 @@ Return Value: // pFileObject->FsContext with NULL, if they are equal, the function puts pOpenContext // into FsContext, and return NULL. Otherwise, it return pFileObject->FsContext without // changing anything. - // - + // + if ((pCurrentOpenContext = InterlockedCompareExchangePointer (& (pFileObject->FsContext), pOpenContext, NULL)) != NULL) { // // pFileObject->FsContext already is used by other open // DEBUGP(DL_WARN, ("ndisprotOpenDevice: FileObject %p already associated" - " with another Open %p/%x\n", + " with another Open %p/%x\n", pFileObject, pCurrentOpenContext, pCurrentOpenContext->Flags)); //BUG - + NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); NPROT_DEREF_OPEN(pOpenContext); // ndisprotOpenDevice failure @@ -766,7 +766,7 @@ Return Value: &BytesProcessed, TRUE // Do wait for power on ); - + if (NdisStatus != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("openDevice: Open %p: set packet filter (%x) failed: %x\n", @@ -781,10 +781,10 @@ Return Value: // for this file object later // pCurrentOpenContext = InterlockedCompareExchangePointer (& (pFileObject->FsContext), NULL, pOpenContext); - - + + NPROT_ASSERT(pCurrentOpenContext == pOpenContext); - + NPROT_SET_FLAGS(pOpenContext->Flags, NPROTO_OPEN_FLAGS, NPROTO_OPEN_IDLE); pOpenContext->pFileObject = NULL; @@ -797,7 +797,7 @@ Return Value: } *ppOpenContext = pOpenContext; - + NtStatus = STATUS_SUCCESS; } while (FALSE); @@ -859,7 +859,7 @@ Return Value: { DEBUGP(DL_INFO, ("DerefOpen: Open %p, Flags %x, ref count is zero!\n", pOpenContext, pOpenContext->Flags)); - + NPROT_ASSERT(pOpenContext->BindingHandle == NULL); NPROT_ASSERT(pOpenContext->RefCount == 0); NPROT_ASSERT(pOpenContext->pFileObject == NULL); diff --git a/network/ndis/ndisprot/6x/sys/protuser.h b/network/ndis/ndisprot/6x/sys/protuser.h index 823d1ef5..31432ed1 100644 --- a/network/ndis/ndisprot/6x/sys/protuser.h +++ b/network/ndis/ndisprot/6x/sys/protuser.h @@ -4,7 +4,7 @@ Copyright (c) 2000 Microsoft Corporation Module Name: - nuiouser.h + protuser.h Abstract: @@ -87,6 +87,6 @@ typedef struct _NDISPROT_QUERY_BINDING ULONG DeviceDescrLength; // in bytes } NDISPROT_QUERY_BINDING, *PNDISPROT_QUERY_BINDING; - + #endif // __NPROTUSER__H diff --git a/network/ndis/ndisprot/6x/sys/recv.c b/network/ndis/ndisprot/6x/sys/recv.c index a7291992..491af751 100644 --- a/network/ndis/ndisprot/6x/sys/recv.c +++ b/network/ndis/ndisprot/6x/sys/recv.c @@ -312,7 +312,7 @@ Return Value: // Copy as much data as possible from the receive packet to // the IRP MDL. // - + pDst = NULL; NdisQueryMdl(pIrp->MdlAddress, &pDst, &BytesRemaining, NormalPagePriority | MdlMappingNoExecute); NPROT_ASSERT(pDst != NULL); // since it was already mapped diff --git a/network/ndis/ndisprot/6x/sys/send.c b/network/ndis/ndisprot/6x/sys/send.c index 73cc282b..17b31051 100644 --- a/network/ndis/ndisprot/6x/sys/send.c +++ b/network/ndis/ndisprot/6x/sys/send.c @@ -35,7 +35,7 @@ NdisprotWrite( Routine Description: - Dispatch routine to handle IRP_MJ_WRITE. + Dispatch routine to handle IRP_MJ_WRITE. Arguments: @@ -73,7 +73,7 @@ Return Value: NtStatus = STATUS_INVALID_HANDLE; break; } - + NPROT_STRUCT_ASSERT(pOpenContext, oc); if (pIrp->MdlAddress == NULL) @@ -86,7 +86,7 @@ Return Value: // // Try to get a virtual address for the MDL. // - + pEthHeader = NULL; NdisQueryMdl(pIrp->MdlAddress, &pEthHeader, &DataLength, NormalPagePriority | MdlMappingNoExecute); @@ -127,14 +127,14 @@ Return Value: NtStatus = STATUS_INVALID_PARAMETER; break; } - + if (!NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN)) { DEBUGP(DL_WARN, ("Write: Failing with invalid Source address")); NtStatus = STATUS_INVALID_PARAMETER; break; } - + NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); @@ -147,13 +147,13 @@ Return Value: NtStatus = STATUS_INVALID_HANDLE; break; - } + } if (pOpenContext->State != NdisprotRunning || pOpenContext->PowerState != NetDeviceStateD0) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); - + DEBUGP(DL_INFO, ("Device is not ready.\n")); NtStatus = STATUS_UNSUCCESSFUL; break; @@ -169,11 +169,11 @@ Return Value: pMdl, 0, // Data offset DataLength); - + if (pNetBufferList == NULL) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); - + DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send net buffer list\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; @@ -192,11 +192,11 @@ Return Value: NPROT_SEND_NBL_RSVD(pNetBufferList)->RefCount = 1; // - // We set up a cancel ID on each send NetBufferList (which maps to a Write IRP), + // We set up a cancel ID on each send NetBufferList (which maps to a Write IRP), // and save the NetBufferList pointer in the IRP. If the IRP gets cancelled, we use // NdisCancelSendNetBufferLists() to cancel the NetBufferList. // - + CancelId = NPROT_GET_NEXT_CANCEL_ID(); NDIS_SET_NET_BUFFER_LIST_CANCEL_ID(pNetBufferList, CancelId); pIrp->Tail.Overlay.DriverContext[0] = (PVOID)pOpenContext; @@ -225,7 +225,7 @@ Return Value: pData = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority | MdlMappingNoExecute); NPROT_ASSERT(pEthHeader == pData); - DEBUGP(DL_VERY_LOUD, + DEBUGP(DL_VERY_LOUD, ("Write: MDL %p, MdlFlags %x, SystemAddr %p, %d bytes\n", pIrp->MdlAddress, pIrp->MdlAddress->MdlFlags, pData, DataLength)); @@ -235,10 +235,10 @@ Return Value: pNetBufferList->SourceHandle = pOpenContext->BindingHandle; ASSERT (NDIS_MDL_LINKAGE(pMdl) == NULL); - + SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK; - NdisSendNetBufferLists( + NdisSendNetBufferLists( pOpenContext->BindingHandle, pNetBufferList, NDIS_DEFAULT_PORT_NUMBER, @@ -285,7 +285,7 @@ Return Value: BOOLEAN FoundIrp = FALSE; UNREFERENCED_PARAMETER(pDeviceObject); - + pOpenContext = (PNDISPROT_OPEN_CONTEXT) pIrp->Tail.Overlay.DriverContext[0]; if (pOpenContext == NULL) { @@ -295,10 +295,10 @@ Return Value: IoReleaseCancelSpinLock(pIrp->CancelIrql); return; } - + NPROT_REF_OPEN(pOpenContext); IoReleaseCancelSpinLock(pIrp->CancelIrql); - + NPROT_STRUCT_ASSERT(pOpenContext, oc); // @@ -320,7 +320,7 @@ Return Value: NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); - if (FoundIrp) + if (FoundIrp) { PVOID CancelId; @@ -344,11 +344,11 @@ Return Value: // DEBUGP(DL_INFO, ("CancelWrite: cancelling nbl %p on Open %p\n", pIrp->Tail.Overlay.DriverContext[1], pOpenContext)); - + NdisCancelSendNetBufferLists( pOpenContext->BindingHandle, CancelId); - + } // // else the send completion routine has already picked up this IRP. @@ -399,7 +399,7 @@ Return Value: CurrNetBufferList = NextNetBufferList) { NextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrNetBufferList); - + pIrp = NPROT_IRP_FROM_SEND_NBL(CurrNetBufferList); IoAcquireCancelSpinLock(&pIrp->CancelIrql); @@ -413,10 +413,10 @@ Return Value: NPROT_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry); NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel); - + CompletionStatus = NET_BUFFER_LIST_STATUS(CurrNetBufferList); - - + + // // We are done with the NDIS_PACKET: // @@ -457,7 +457,7 @@ Return Value: NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP } - + } diff --git a/network/ndis/ndisprot/6x/test/prottest.c b/network/ndis/ndisprot/6x/test/prottest.c index 54af3ddc..c743bed5 100644 --- a/network/ndis/ndisprot/6x/test/prottest.c +++ b/network/ndis/ndisprot/6x/test/prottest.c @@ -379,6 +379,7 @@ GetSrcMac( BytesReturned)); #pragma warning(suppress:6202) // buffer overrun warning - enough space allocated in QueryBuffer + // codeql[cpp/buffer-overflow] memcpy(pSrcMacAddr, pQueryOid->Data, MAC_ADDR_LEN); } else diff --git a/network/ndis/ndisprot_kmdf/60/debug.c b/network/ndis/ndisprot_kmdf/60/debug.c index 59471e3f..af6bc053 100644 --- a/network/ndis/ndisprot_kmdf/60/debug.c +++ b/network/ndis/ndisprot_kmdf/60/debug.c @@ -39,7 +39,7 @@ ndisprotAuditAllocMem( ) { PVOID pBuffer; - PNPROTD_ALLOCATION pAllocInfo; + PNPROTD_ALLOCATION pAllocInfo = NULL; if (!ndisprotdInitDone) { diff --git a/network/ndis/ndisprot_kmdf/60/ndisbind.c b/network/ndis/ndisprot_kmdf/60/ndisbind.c index 0878e198..32272f93 100644 --- a/network/ndis/ndisprot_kmdf/60/ndisbind.c +++ b/network/ndis/ndisprot_kmdf/60/ndisbind.c @@ -61,14 +61,17 @@ Routine Description: Arguments: + ProtocolDriverContext - handle to the protocol driver context + BindContext - handle to the bind context provided by NDIS + BindParameters - parameters describing the adapter to which we are binding Return Value: - None + NDIS_STATUS_SUCCESS if successful, failure code otherwise. --*/ { - PNDISPROT_OPEN_CONTEXT pOpenContext; + PNDISPROT_OPEN_CONTEXT pOpenContext = NULL; NDIS_STATUS Status; WDF_IO_QUEUE_CONFIG queueConfig; NTSTATUS ntStatus; @@ -1334,9 +1337,9 @@ Return Value: while (FALSE); DEBUGP(DL_LOUD, ("ValidateOpenAndDoReq: Open %p/%x, OID %x, Status %x\n", - pOpenContext, - pOpenContext == NULL ? 0 : pOpenContext->Flags, - Oid, + pOpenContext, + pOpenContext == NULL ? 0 : pOpenContext->Flags, + Oid, Status)); return (Status); diff --git a/network/ndis/ndisprot_kmdf/60/protuser.h b/network/ndis/ndisprot_kmdf/60/protuser.h index 44a57c95..cba3a678 100644 --- a/network/ndis/ndisprot_kmdf/60/protuser.h +++ b/network/ndis/ndisprot_kmdf/60/protuser.h @@ -4,7 +4,7 @@ Copyright (c) 2000 Microsoft Corporation Module Name: - nuiouser.h + protuser.h Abstract: diff --git a/network/ndis/ndisprot_kmdf/60/send.c b/network/ndis/ndisprot_kmdf/60/send.c index 5c009939..31efd03c 100644 --- a/network/ndis/ndisprot_kmdf/60/send.c +++ b/network/ndis/ndisprot_kmdf/60/send.c @@ -37,10 +37,10 @@ Arguments: Queue - Default queue handle Request - Handle to the read/write request - Lenght - Length of the data buffer associated with the request. + Length - Length of the data buffer associated with the request. The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get + zero length read & write requests to the driver and + complete it with status success. So we will never get a zero length request. Return Value: diff --git a/network/ndis/ndisprot_kmdf/notifyob/dllmain.cpp b/network/ndis/ndisprot_kmdf/notifyob/dllmain.cpp index 2452d95c..2414ceee 100644 --- a/network/ndis/ndisprot_kmdf/notifyob/dllmain.cpp +++ b/network/ndis/ndisprot_kmdf/notifyob/dllmain.cpp @@ -12,10 +12,10 @@ Abstract: notify object dll and the Wdf Coinstaller library. --*/ - + #include "Common.hpp" #include <DriverSpecs.h> -_Analysis_mode_(_Analysis_code_type_user_code_) +_Analysis_mode_(_Analysis_code_type_user_code_) #include <strsafe.h> #include "ProtNotify_i.c" @@ -61,7 +61,7 @@ DllMain( if (Reason == DLL_PROCESS_ATTACH) { // // Initialize the COM Server module with the object map. - // Do this prior to loading the coinstaller as the detach + // Do this prior to loading the coinstaller as the detach // assumes the Module is initialized. // _Module.Init(ObjectMap, Instance); @@ -159,8 +159,8 @@ HMODULE LoadWdfCoInstaller( ) { - - #pragma prefast(suppress:6262, "Supprress overflow warnings") + + #pragma prefast(suppress:6262, "Supprress overflow warnings") HRESULT hr = S_OK; HMODULE library = NULL; WCHAR coinstaller[MAX_PATH] = {0}; @@ -190,7 +190,7 @@ LoadWdfCoInstaller( // // Load the Wdf Coinstaller library. // -#pragma prefast(suppress:28160, "Suppressing false positive from PFD") +#pragma prefast(suppress:28160, "Suppressing false positive from PFD") library = LoadLibrary(coinstaller); if (library == NULL) { hr = GetLastError(); diff --git a/network/ndis/netvmini/6x/60/netvmini60.rc b/network/ndis/netvmini/6x/60/netvmini60.rc index ac470534..a01b2097 100644 --- a/network/ndis/netvmini/6x/60/netvmini60.rc +++ b/network/ndis/netvmini/6x/60/netvmini60.rc @@ -9,7 +9,7 @@ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: - netvmini.rc + netvmini60.rc Abstract: diff --git a/network/ndis/netvmini/6x/620/netvmini620.rc b/network/ndis/netvmini/6x/620/netvmini620.rc index 72dba137..ddd4495d 100644 --- a/network/ndis/netvmini/6x/620/netvmini620.rc +++ b/network/ndis/netvmini/6x/620/netvmini620.rc @@ -9,7 +9,7 @@ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: - netvmini.rc + netvmini620.rc Abstract: diff --git a/network/ndis/netvmini/6x/adapter.c b/network/ndis/netvmini/6x/adapter.c index 3cf0ce59..1dd3e312 100644 --- a/network/ndis/netvmini/6x/adapter.c +++ b/network/ndis/netvmini/6x/adapter.c @@ -552,7 +552,7 @@ Routine Description: send requests must be completed, and new requests must be rejected with NDIS_STATUS_PAUSED. - Once all sends have been completed and all recieve NBLs have returned to + Once all sends have been completed and all receive NBLs have returned to the miniport, the miniport enters the Paused state. While paused, the miniport can still service interrupts from the hardware @@ -2281,7 +2281,7 @@ Arguments: Return Value: - NDIS_STATUS_SUCCESS if reference was acquired succesfully. + NDIS_STATUS_SUCCESS if reference was acquired successfully. NDIS_STATUS_ADAPTER_NOT_READY if the adapter state is such that we should not acquire new references to resources --*/ diff --git a/network/ndis/netvmini/6x/adapter.h b/network/ndis/netvmini/6x/adapter.h index cfc540d3..92d84508 100644 --- a/network/ndis/netvmini/6x/adapter.h +++ b/network/ndis/netvmini/6x/adapter.h @@ -52,14 +52,14 @@ typedef struct _MP_ADAPTER_RECEIVE_DPC { LIST_ENTRY Entry; // - // Kernel DPC used for recieve + // Kernel DPC used for receive // KDPC Dpc; USHORT ProcessorGroup; ULONG ProcessorNumber; // - // Tracks which receive blocks need to be recieved on this DPC. + // Tracks which receive blocks need to be received on this DPC. // BOOLEAN RecvBlock[NIC_SUPPORTED_NUM_QUEUES]; volatile LONG RecvBlockCount; diff --git a/network/ndis/netvmini/6x/ctrlpath.c b/network/ndis/netvmini/6x/ctrlpath.c index 6a745a36..3864420a 100644 --- a/network/ndis/netvmini/6x/ctrlpath.c +++ b/network/ndis/netvmini/6x/ctrlpath.c @@ -20,6 +20,7 @@ Abstract: #include "netvmin6.h" +#include <ntintsafe.h> #include "ctrlpath.tmh" @@ -223,7 +224,7 @@ MPSynchronousOidRequest( Routine Description: - Entry point called by NDIS to get or set the value of a specified + Entry point called by NDIS to get or set the value of a specified synchronous OID. Arguments: @@ -516,7 +517,7 @@ Return Value: #if (NDIS_SUPPORT_NDIS61 && !NDIS_SUPPORT_NDIS620) case OID_PNP_CAPABILITIES: // - // This OID is obsolete for NDIS 6.20 drivers + // This OID is obsolete for NDIS 6.20 drivers // // Return the wake-up capabilities of its NIC. If you return // NDIS_STATUS_NOT_SUPPORTED, NDIS considers the miniport driver @@ -773,7 +774,7 @@ Return Value: case OID_GEN_INTERRUPT_MODERATION: { PNDIS_INTERRUPT_MODERATION_PARAMETERS Moderation = (PNDIS_INTERRUPT_MODERATION_PARAMETERS)Query->InformationBuffer; - Moderation->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + Moderation->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; Moderation->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1; Moderation->Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1; Moderation->Flags = 0; @@ -906,10 +907,10 @@ Return Value: case OID_RECEIVE_FILTER_FREE_QUEUE: // - // Free the requested receive queue. + // Free the requested receive queue. // Status = NICFreeRxQueue( - Adapter, + Adapter, NdisSetRequest); break; @@ -928,17 +929,17 @@ Return Value: // Status = NICUpdateRxQueue( Adapter, - NdisSetRequest); + NdisSetRequest); break; #endif case OID_PNP_SET_POWER: // - // Update power state + // Update power state // Status = MPSetPower( Adapter, - NdisSetRequest); + NdisSetRequest); break; #if (NDIS_SUPPORT_NDIS680) @@ -962,7 +963,7 @@ Return Value: case OID_PNP_REMOVE_WAKE_UP_PATTERN: case OID_PNP_ENABLE_WAKE_UP: #endif - ASSERT(!"NIC does not support wake on LAN OIDs"); + ASSERT(!"NIC does not support wake on LAN OIDs"); default: Status = NDIS_STATUS_NOT_SUPPORTED; break; @@ -1015,24 +1016,24 @@ Return Value: switch (Oid) { - + #if (NDIS_SUPPORT_NDIS620) case OID_RECEIVE_FILTER_ALLOCATE_QUEUE: // // Allocate the requested receive queue. // Status = NICAllocateRxQueue( - Adapter, + Adapter, NdisRequest); break; case OID_RECEIVE_FILTER_QUEUE_ALLOCATION_COMPLETE: // - // Complete any remaining allocation for receive queues. + // Complete any remaining allocation for receive queues. // Status = NICCompleteAllocationRxQueue( - Adapter, + Adapter, NdisRequest); break; @@ -1305,7 +1306,7 @@ NICAllocateRxQueue( Routine Description: This routine will allocate a receive queue according to the passed in allocation request. It verifies that the request - is well formed, then passes the request to underlying queue management code. + is well formed, then passes the request to underlying queue management code. Arguments: @@ -1321,22 +1322,22 @@ Return Value: NDIS_STATUS Status = NDIS_STATUS_SUCCESS; struct _METHOD *Method = &NdisMethodRequest->DATA.METHOD_INFORMATION; PNDIS_RECEIVE_QUEUE_PARAMETERS QueueParams = (PNDIS_RECEIVE_QUEUE_PARAMETERS)Method->InformationBuffer; - + PAGED_CODE(); DEBUGP(MP_TRACE, "[%p] ---> NICAllocateRxQueue\n", Adapter); - + do { // // Verify that the request matches our requirements // - VERIFY_OID_METHOD(NdisMethodRequest, - NDIS_RECEIVE_QUEUE_PARAMETERS_REVISION_1, + VERIFY_OID_METHOD(NdisMethodRequest, + NDIS_RECEIVE_QUEUE_PARAMETERS_REVISION_1, NDIS_SIZEOF_RECEIVE_QUEUE_PARAMETERS_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // Method->BytesRead = NDIS_SIZEOF_RECEIVE_QUEUE_PARAMETERS_REVISION_1; @@ -1373,7 +1374,7 @@ NICCompleteAllocationRxQueue( Routine Description: This routine will complete any remaining queue allocation, including shared memory. It verifies that the request - is well formed, then passes the request to underlying queue management code. + is well formed, then passes the request to underlying queue management code. Arguments: @@ -1384,7 +1385,7 @@ Return Value: NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; @@ -1394,21 +1395,21 @@ Return Value: PAGED_CODE(); DEBUGP(MP_TRACE, "[%p] ---> NICCompleteAllocationRxQueue\n", Adapter); - + do { // // Verify that the request matches our requirements // - VERIFY_OID_METHOD(NdisMethodRequest, - NDIS_RECEIVE_QUEUE_ALLOCATION_COMPLETE_ARRAY_REVISION_1, + VERIFY_OID_METHOD(NdisMethodRequest, + NDIS_RECEIVE_QUEUE_ALLOCATION_COMPLETE_ARRAY_REVISION_1, NDIS_SIZEOF_RECEIVE_QUEUE_ALLOCATION_COMPLETE_ARRAY_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // - Method->BytesRead = NDIS_SIZEOF_RECEIVE_QUEUE_ALLOCATION_COMPLETE_ARRAY_REVISION_1+ + Method->BytesRead = NDIS_SIZEOF_RECEIVE_QUEUE_ALLOCATION_COMPLETE_ARRAY_REVISION_1+ (CompleteArray->NumElements * CompleteArray->ElementSize); // @@ -1417,9 +1418,9 @@ Return Value: Status = CompleteAllocationRxQueue(Adapter, CompleteArray); }while(FALSE); - + DEBUGP(MP_TRACE, "[%p] <--- NICCompleteAllocationRxQueue Status 0x%08x\n", Adapter, Status); - + return Status; } @@ -1432,7 +1433,7 @@ NICFreeRxQueue( Routine Description: This routine will handle the passed in queue free request. It verifies that the request - is well formed, then passes the request to underlying queue management code. + is well formed, then passes the request to underlying queue management code. Arguments: @@ -1452,21 +1453,21 @@ Return Value: PAGED_CODE(); DEBUGP(MP_TRACE, "[%p] ---> NICFreeRxQueue\n", Adapter); - + do { // // Verify that the request matches our requirements // - VERIFY_OID_SET(NdisSetRequest, - NDIS_RECEIVE_QUEUE_FREE_PARAMETERS_REVISION_1, + VERIFY_OID_SET(NdisSetRequest, + NDIS_RECEIVE_QUEUE_FREE_PARAMETERS_REVISION_1, NDIS_SIZEOF_RECEIVE_QUEUE_FREE_PARAMETERS_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // Set->BytesRead = NDIS_SIZEOF_RECEIVE_QUEUE_FREE_PARAMETERS_REVISION_1; - + // // Default queue cannot be freed // @@ -1478,14 +1479,14 @@ Return Value: } // - // Ready to attempt a free. + // Ready to attempt a free. // Status = FreeRxQueue(Adapter, QueueFreeParams, NdisSetRequest); }while(FALSE); - + DEBUGP(MP_TRACE, "[%p] <--- NICFreeRxQueuee Status 0x%08x\n", Adapter, Status); - + return Status; } @@ -1498,7 +1499,7 @@ NICSetRxFilter( Routine Description: This routine will handle the passed filter set request. It verifies that the request - is well formed, then passes the request to underlying filter management code. + is well formed, then passes the request to underlying filter management code. Arguments: @@ -1509,7 +1510,7 @@ Return Value: NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; @@ -1523,12 +1524,12 @@ Return Value: // // Verify that the request matches our requirements // - VERIFY_OID_METHOD(NdisMethodRequest, - NDIS_RECEIVE_FILTER_PARAMETERS_REVISION_1, + VERIFY_OID_METHOD(NdisMethodRequest, + NDIS_RECEIVE_FILTER_PARAMETERS_REVISION_1, NDIS_SIZEOF_RECEIVE_FILTER_PARAMETERS_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // Method->BytesRead = NDIS_SIZEOF_RECEIVE_FILTER_PARAMETERS_REVISION_1; @@ -1536,7 +1537,7 @@ Return Value: // Ready to set Filter // Status = SetRxFilter(Adapter, FilterParams); - + }while(FALSE); return Status; @@ -1551,7 +1552,7 @@ NICClearRxFilter( Routine Description: This routine will handle the passed filter clear request. It verifies that the request - is well formed, then passes the request to underlying filter management code. + is well formed, then passes the request to underlying filter management code. Arguments: @@ -1562,7 +1563,7 @@ Return Value: NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; struct _SET *Set = &NdisSetRequest->DATA.SET_INFORMATION; @@ -1576,15 +1577,15 @@ Return Value: // // Verify that the request matches our requirements // - VERIFY_OID_SET(NdisSetRequest, - NDIS_RECEIVE_FILTER_CLEAR_PARAMETERS_REVISION_1, + VERIFY_OID_SET(NdisSetRequest, + NDIS_RECEIVE_FILTER_CLEAR_PARAMETERS_REVISION_1, NDIS_SIZEOF_RECEIVE_FILTER_CLEAR_PARAMETERS_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // Set->BytesRead = NDIS_SIZEOF_RECEIVE_FILTER_CLEAR_PARAMETERS_REVISION_1; - + // // Ready to clear the filter // @@ -1613,15 +1614,15 @@ NICUpdateRxQueue( // // Verify that the request matches our requirements // - VERIFY_OID_SET(NdisSetRequest, - NDIS_RECEIVE_QUEUE_PARAMETERS_REVISION_1, + VERIFY_OID_SET(NdisSetRequest, + NDIS_RECEIVE_QUEUE_PARAMETERS_REVISION_1, NDIS_SIZEOF_RECEIVE_QUEUE_PARAMETERS_REVISION_1); // - // Request is well formed, set bytes read + // Request is well formed, set bytes read // Set->BytesRead = NDIS_SIZEOF_RECEIVE_FILTER_CLEAR_PARAMETERS_REVISION_1; - + // // Ready to clear the filter // @@ -1671,6 +1672,9 @@ Return Value: do { + ULONG ClassificationBytes = 0; + ULONG BytesRead = 0; + // // Verify that the request matches our requirements. // @@ -1681,8 +1685,18 @@ Return Value: // // Request is well formed, set bytes read. // - Method->BytesRead = NDIS_SIZEOF_QOS_PARAMETERS_REVISION_1 + - Params->NumClassificationElements * Params->ClassificationElementSize; + if (!NT_SUCCESS(RtlULongMult(Params->NumClassificationElements, + Params->ClassificationElementSize, + &ClassificationBytes)) || + !NT_SUCCESS(RtlULongAdd(NDIS_SIZEOF_QOS_PARAMETERS_REVISION_1, + ClassificationBytes, + &BytesRead))) + { + Status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + Method->BytesRead = BytesRead; Status = SetQOSParameters(Adapter, Params); if (Status != NDIS_STATUS_SUCCESS) @@ -1711,7 +1725,7 @@ MPSetPower( /*++ Routine Description: - This routine handles OID_PNP_SET_POWER request. + This routine handles OID_PNP_SET_POWER request. Arguments: @@ -1720,9 +1734,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; struct _SET *Set = &NdisSetRequest->DATA.SET_INFORMATION; @@ -1775,9 +1789,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; @@ -1799,19 +1813,19 @@ MPSetPowerLow( /*++ Routine Description: - The NIC is about to be transitioned to a low power state. + The NIC is about to be transitioned to a low power state. Prepare the NIC for the sleeping state: - - Disable interrupts and the NIC's DMA engine, cancel timers. - - Save any hardware context that the NIC cannot preserve in - a sleeping state (packet filters, multicast addresses, + - Disable interrupts and the NIC's DMA engine, cancel timers. + - Save any hardware context that the NIC cannot preserve in + a sleeping state (packet filters, multicast addresses, the current MAC address, etc.) - A miniport driver cannot access the NIC hardware after + A miniport driver cannot access the NIC hardware after the NIC has been set to the D3 state by the bus driver. - Miniport drivers NDIS v6.30 and above - Do NOT wait for NDIS to return the ownership of all + Miniport drivers NDIS v6.30 and above + Do NOT wait for NDIS to return the ownership of all NBLs from outstanding receive indications - Retain ownership of all the receive descriptors and + Retain ownership of all the receive descriptors and packet buffers previously owned by the hardware. Arguments: @@ -1821,9 +1835,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; LONG nSendWaitCount = 0; @@ -1837,8 +1851,8 @@ Return Value: #if (NDIS_SUPPORT_NDIS630) // - // Miniport drivers NDIS v6.30 and above are not - // necessarily paused prior the low power transition + // Miniport drivers NDIS v6.30 and above are not + // necessarily paused prior the low power transition // // @@ -1848,7 +1862,7 @@ Return Value: // // Wait for outstanding sends - // Do NOT wait for outstanding receives + // Do NOT wait for outstanding receives // while(Adapter->nBusySend) { @@ -1867,8 +1881,8 @@ Return Value: UNREFERENCED_PARAMETER(nSendWaitCount); // - // Miniport drivers NDIS v6.20 and below are - // paused prior the low power transition + // Miniport drivers NDIS v6.20 and below are + // paused prior the low power transition // ASSERT(MP_TEST_FLAG(Adapter, fMP_ADAPTER_PAUSED)); ASSERT(!NICIsBusy(Adapter)); @@ -1888,7 +1902,7 @@ MPSetRSSv2Parameters( /*++ Routine Description: - This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request. + This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request. Arguments: @@ -1897,9 +1911,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { struct _SET *Set; @@ -1908,7 +1922,7 @@ Return Value: // // Validate the request // - if (Set->InformationBufferLength < + if (Set->InformationBufferLength < NDIS_SIZEOF_RECEIVE_SCALE_PARAMETERS_V2_REVISION_1) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid InformationBufferLength\n"); @@ -1928,7 +1942,7 @@ MPSetRSSv2IndirectionTableEntries( /*++ Routine Description: - This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request. + This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request. Arguments: @@ -1937,9 +1951,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { struct _METHOD *Method; @@ -1950,7 +1964,7 @@ Return Value: // // Validate the request // - if (Method->InputBufferLength < + if (Method->InputBufferLength < NDIS_SIZEOF_RSS_SET_INDIRECTION_ENTRIES_REVISION_1) { DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid InformationBufferLength\n"); diff --git a/network/ndis/netvmini/6x/datapath.c b/network/ndis/netvmini/6x/datapath.c index 1c18094c..19b7cb6c 100644 --- a/network/ndis/netvmini/6x/datapath.c +++ b/network/ndis/netvmini/6x/datapath.c @@ -755,7 +755,7 @@ Arguments: Return Value: - NDIS_STATUS_SUCCESS if reference was acquired succesfully. + NDIS_STATUS_SUCCESS if reference was acquired successfully. NDIS_STATUS_ADAPTER_NOT_READY if the adapter state is such that we should not acquire new references to resources --*/ diff --git a/network/ndis/netvmini/6x/hardware.h b/network/ndis/netvmini/6x/hardware.h index ddc4c4a3..3b0731b0 100644 --- a/network/ndis/netvmini/6x/hardware.h +++ b/network/ndis/netvmini/6x/hardware.h @@ -130,7 +130,7 @@ C_ASSERT(sizeof(NIC_FRAME_HEADER) == HW_FRAME_HEADER_SIZE); // // Maximum number of receives that will be processed per DPC. -// This constraints the amount of time spent for a single receive DPC. +// This constraints the amount of time spent for a single receive DPC. // #define NIC_MAX_RECVS_PER_DPC 64 @@ -179,9 +179,9 @@ C_ASSERT(sizeof(NIC_FRAME_HEADER) == HW_FRAME_HEADER_SIZE); // and suspend. Ensure the correct flags are set for your hardware. // // If your hardware supports busmaster DMA, you must specify -// NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER. Our virtual miniport will -// not be allocating hardware resources such as interrupts, so we set the -// WDM attribute. +// NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER. Our virtual miniport will +// not be allocating hardware resources such as interrupts, so we set the +// WDM attribute. // #define NIC_ADAPTER_ATTRIBUTES_FLAGS (\ NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK | NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM) @@ -239,21 +239,21 @@ C_ASSERT(sizeof(NIC_FRAME_HEADER) == HW_FRAME_HEADER_SIZE); // // The NIC must reserve at least one filter available HW queue. More filters allows // the VMQ queues to be assigned asymmetrically. For this sample we chose to allow -// twice as many filters as queues. +// twice as many filters as queues. // #define NIC_SUPPORTED_NUM_QUEUES 8 #define NIC_MAX_HEADER_FILTERS (NIC_SUPPORTED_NUM_QUEUES*2) // // Determines the minimum and maximum amount of lookahead split that we can do. Real hardware -// might have tighter constraints on the range depending on the HW design. +// might have tighter constraints on the range depending on the HW design. // #define NIC_MIN_LOOKAHEAD_SPLIT 64 #define NIC_MAX_LOOKAHEAD_SPLIT 128 // // Determines the minimum amount of receive blocks we will attempt to allocate if the full allocations fail and -// we retry with a reduced count. If we fail with this amount we fail the allocation. +// we retry with a reduced count. If we fail with this amount we fail the allocation. // #define NIC_MIN_BUSY_RECVS 64 diff --git a/network/ndis/netvmini/6x/miniport.c b/network/ndis/netvmini/6x/miniport.c index 9ec793af..5526789f 100644 --- a/network/ndis/netvmini/6x/miniport.c +++ b/network/ndis/netvmini/6x/miniport.c @@ -344,7 +344,7 @@ VOID MPAttachAdapter( _In_ PMP_ADAPTER Adapter) { - MP_LOCK_STATE LockState; + MP_LOCK_STATE LockState; DEBUGP(MP_TRACE, "[%p] ---> MPAttachAdapter\n", Adapter); diff --git a/network/ndis/netvmini/6x/miniport.h b/network/ndis/netvmini/6x/miniport.h index 364ad704..77d68599 100644 --- a/network/ndis/netvmini/6x/miniport.h +++ b/network/ndis/netvmini/6x/miniport.h @@ -19,7 +19,7 @@ Abstract: 1. Set the correct driver version number for your versioning scheme. 2. Create unique memory allocation tags. - --*/ +--*/ #ifndef _MINIPORT_H diff --git a/network/ndis/netvmini/6x/mphal.c b/network/ndis/netvmini/6x/mphal.c index e363f613..63aff834 100644 --- a/network/ndis/netvmini/6x/mphal.c +++ b/network/ndis/netvmini/6x/mphal.c @@ -90,7 +90,7 @@ Return Value: case CmResourceTypePort: DEBUGP(MP_INFO, "[%p] IoBaseAddress = 0x%x\n", Adapter, NdisGetPhysicalAddressLow(pResDesc->u.Port.Start)); - DEBUGP(MP_INFO, "[%p] IoRange = x%x\n", Adapter, + DEBUGP(MP_INFO, "[%p] IoRange = x%x\n", Adapter, pResDesc->u.Port.Length); break; @@ -173,7 +173,7 @@ Return Value: NDIS_STATUS Status; PNDIS_CONFIGURATION_PARAMETER Parameter = NULL; NDIS_STRING PermanentAddressKey = RTL_CONSTANT_STRING(NETVMINI_MAC_ADDRESS_KEY); - + UNREFERENCED_PARAMETER(Adapter); PAGED_CODE(); @@ -234,7 +234,7 @@ Return Value: PermanentMacAddress[2] = 0xF2; // - // Generated value based on the current tick count value. + // Generated value based on the current tick count value. // KeQueryTickCount(&TickCountValue); do @@ -455,9 +455,9 @@ HWCopyBytesFromNetBuffer( Routine Description: - Copies the first cbDest bytes from a NET_BUFFER. In order to show how the various data structures fit together, this + Copies the first cbDest bytes from a NET_BUFFER. In order to show how the various data structures fit together, this implementation copies the data by iterating through the MDLs for the NET_BUFFER. The NdisGetDataBuffer API also allows you - to copy a contiguous block of data from a NET_BUFFER. + to copy a contiguous block of data from a NET_BUFFER. Runs at IRQL <= DISPATCH_LEVEL. @@ -496,8 +496,8 @@ Notes: while (DestOffset < *cbDest && CurrentMdl) { // - // Map MDL memory to System Address Space. LowPagePriority means mapping may fail if - // system is low on memory resources. + // Map MDL memory to System Address Space. LowPagePriority means mapping may fail if + // system is low on memory resources. // PUCHAR SrcMemory = MmGetSystemAddressForMdlSafe(CurrentMdl, LowPagePriority | MdlMappingNoExecute); ULONG Length = MmGetMdlByteCount(CurrentMdl); @@ -526,7 +526,7 @@ Notes: DestOffset += Length; // - // Get next MDL (if any available) + // Get next MDL (if any available) // CurrentMdl = NDIS_MDL_LINKAGE(CurrentMdl); } @@ -837,12 +837,12 @@ Return Value: // - // For simplicity in the sample in order to support VLAN we extract the information from the NBL or frame and pass the + // For simplicity in the sample in order to support VLAN we extract the information from the NBL or frame and pass the // NDIS_NET_BUFFER_LIST_8021Q_INFO structure to the code that simulates the send/receive. The code does nothing to convert - // modify the frame format. + // modify the frame format. // In real HW, on send the code should extract the information from the NBL and covert it to 802.1Q format for transmission, and // on receive the adapter should detect if the packet is in 802.1Q format and if so convert it back to 802.3 before indicating it up to NDIS - // (populating the 8021Q info in the NBL being indicated). + // (populating the 8021Q info in the NBL being indicated). // Nbl = NBL_FROM_SEND_NB(NetBuffer); Nbl1QInfo.Value = NET_BUFFER_LIST_INFO(Nbl, Ieee8021QNetBufferListInfo); @@ -854,7 +854,7 @@ Return Value: else { DEBUGP(MP_TRACE, "[%p] Send NBL (%p) has no OOB VLAN tag, checking frame header.\n", Adapter, Nbl); - if(IS_FRAME_8021Q(Frame)) + if(IS_FRAME_8021Q(Frame)) { // // The frame has type of 802.1Q. Retrieve the VLAN information @@ -864,9 +864,9 @@ Return Value: } else { - DEBUGP(MP_TRACE, "[%p] Send NBL (%p) has no VLAN information in its frame header.\n", Adapter, Nbl); + DEBUGP(MP_TRACE, "[%p] Send NBL (%p) has no VLAN information in its frame header.\n", Adapter, Nbl); } - } + } RXDeliverFrameToEveryAdapter(Adapter, &Nbl1QInfo, Frame, fAtDispatch); @@ -923,8 +923,8 @@ HWBeginReceiveDma( Routine Description: - Simulate the hardware deciding to receive a FRAME into one of its RCBs. In VMQ enabled scenarios, it will - find the matching queue and if matched retrieve the shared memory for the queue for the NBL. Otherwise, it + Simulate the hardware deciding to receive a FRAME into one of its RCBs. In VMQ enabled scenarios, it will + find the matching queue and if matched retrieve the shared memory for the queue for the NBL. Otherwise, it uses the existing Frame for the NBL. Arguments: @@ -949,7 +949,7 @@ Return Value: DEBUGP(MP_TRACE, "[%p] ---> HWBeginReceiveDma. Frame: 0x%p\n", Adapter, Frame); // - // Preserve 802.1Q information, if specified. + // Preserve 802.1Q information, if specified. // if(Nbl1QInfo->Value) { @@ -963,7 +963,7 @@ Return Value: } // - // If VMQ is enabled, and we're not using the default queue, + // If VMQ is enabled, and we're not using the default queue, // we need to copy the FRAME to the NBL's shared memory area // if(VMQ_ENABLED(Adapter)) @@ -991,12 +991,12 @@ Return Value: NET_BUFFER_DATA_OFFSET(NetBuffer) = 0; NET_BUFFER_CURRENT_MDL(NetBuffer) = NET_BUFFER_FIRST_MDL(NetBuffer); NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer) = 0; - + } while(FALSE); - + DEBUGP(MP_TRACE, "[%p] <--- HWBeginReceiveDma Status 0x%08x\n", Adapter, Status); return Status; } - + diff --git a/network/ndis/netvmini/6x/mphal.h b/network/ndis/netvmini/6x/mphal.h index 5348545b..0bcd11e6 100644 --- a/network/ndis/netvmini/6x/mphal.h +++ b/network/ndis/netvmini/6x/mphal.h @@ -51,7 +51,7 @@ struct _RCB; typedef struct _VLAN_TAG_HEADER { - UCHAR TagInfo[2]; + UCHAR TagInfo[2]; } VLAN_TAG_HEADER, *PVLAN_TAG_HEADER; #define GET_FRAME_VLAN_TAG_HEADER(_Frame)\ diff --git a/network/ndis/netvmini/6x/qos.c b/network/ndis/netvmini/6x/qos.c index a7b2e530..fe455b1b 100644 --- a/network/ndis/netvmini/6x/qos.c +++ b/network/ndis/netvmini/6x/qos.c @@ -637,7 +637,7 @@ Return Value: IndicateParameters(Adapter, NDIS_STATUS_QOS_OPERATIONAL_PARAMETERS_CHANGE, OperationalParams); - + NdisFreeMemoryWithTagPriority(NdisDriverHandle, OperationalParams, NIC_TAG_QOS_PARAMS); } else diff --git a/network/ndis/netvmini/6x/rssv2.c b/network/ndis/netvmini/6x/rssv2.c index 1f8efb0e..481c4f5e 100644 --- a/network/ndis/netvmini/6x/rssv2.c +++ b/network/ndis/netvmini/6x/rssv2.c @@ -51,10 +51,10 @@ Arguments: Vport - Pointer to the VPort - Command - Move command which identifies the steering + Command - Move command which identifies the steering parameter and the target processor. - NewLocalCpuIndex - Local index of the target processor the steering + NewLocalCpuIndex - Local index of the target processor the steering parameter is being pointed to. Return Value: @@ -74,13 +74,13 @@ MiniportApplyConfigurationToHW( _Inout_ PMP_ADAPTER Adapter, _Inout_ PMP_ADAPTER_VPORT VPort, _In_ BOOLEAN IsRssEnabled, - _In_ USHORT NewITCount, + _In_ USHORT NewITCount, _In_ ULONG NewNumberOfQueues ) /*++ Routine Description: - This routine propagates changes as specified by the configuration OID to + This routine propagates changes as specified by the configuration OID to the HW. All failures cases are already handled and before calling this function. @@ -109,7 +109,7 @@ Return Value: UNREFERENCED_PARAMETER(NewITCount); UNREFERENCED_PARAMETER(NewNumberOfQueues); } - + _IRQL_requires_(PASSIVE_LEVEL) NDIS_STATUS @@ -152,8 +152,8 @@ Return Value: // // Allocate the neccessary memory for reading the available processors // - Adapter->RSSData.RssProcessorInfo = - (PNDIS_RSS_PROCESSOR_INFO)ExAllocatePool2(POOL_FLAG_NON_PAGED, + Adapter->RSSData.RssProcessorInfo = + (PNDIS_RSS_PROCESSOR_INFO)ExAllocatePool2(POOL_FLAG_NON_PAGED, RssInfoSize, 'IRMT'); if (Adapter->RSSData.RssProcessorInfo == NULL) @@ -166,7 +166,7 @@ Return Value: Status = NdisGetRssProcessorInformation(Adapter->AdapterHandle, Adapter->RSSData.RssProcessorInfo, &RssInfoSize); - + if (Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, "%s: Unabled to get rss information\n", __FUNCTION__); @@ -174,7 +174,7 @@ Return Value: } Adapter->RSSData.RssProcessorArray = (PNDIS_RSS_PROCESSOR) - ((PUCHAR)Adapter->RSSData.RssProcessorInfo + + ((PUCHAR)Adapter->RSSData.RssProcessorInfo + Adapter->RSSData.RssProcessorInfo->RssProcessorArrayOffset); Status = NDIS_STATUS_SUCCESS; @@ -210,19 +210,19 @@ Return Value: --*/ { - UINT8 index; + ULONG index; PNDIS_RSS_PROCESSOR processor; - for (index = 0; - index < Adapter->RSSData.RssProcessorInfo->RssProcessorCount; + for (index = 0; + index < Adapter->RSSData.RssProcessorInfo->RssProcessorCount; index++) { processor = &Adapter->RSSData.RssProcessorArray[index]; - if ((processor->ProcNum.Group == ProcessorNumber.Group) && + if ((processor->ProcNum.Group == ProcessorNumber.Group) && (processor->ProcNum.Number == ProcessorNumber.Number)) { - return index; + return (UINT8)index; } } @@ -274,7 +274,7 @@ NICSetRSSv2ValidateRssProcessor( /*++ Routine Description: - This routine validates processor against minport's RSS settings, and if it + This routine validates processor against minport's RSS settings, and if it is valid, returns local index. Arguments: @@ -322,7 +322,7 @@ Return Value: if ((ProcessorNumber.Group == (USHORT)RssProcessorInfo->RssMaxProcessor.Group) && (ProcessorNumber.Number > (UCHAR)RssProcessorInfo->RssMaxProcessor.Number)) { - DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Number %d:%d, above RssMaxProcNumber\n", + DEBUGP(MP_ERROR, "RssValidateProcessor: Invalid Proc Number %d:%d, above RssMaxProcNumber\n", ProcessorNumber.Group, ProcessorNumber.Number); return FALSE; } @@ -373,7 +373,7 @@ Return Value: VPort->RssEnabled = FALSE; if (!NICSetRSSv2ValidateRssProcessor(Adapter, - PrimaryProcessor, + PrimaryProcessor, &PrimaryProcessorIndex)) { DEBUGP(MP_TRACE, "Primary is not a valid RSS processor.\n"); @@ -393,7 +393,7 @@ Return Value: goto Cleanup; } - RssV2NQEnforcerInitialize(VPort->QueueMap, + RssV2NQEnforcerInitialize(VPort->QueueMap, RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE); RtlFillMemory(&VPort->RssV2IndexTable, sizeof(VPort->RssV2IndexTable), 0xFF); @@ -430,7 +430,7 @@ NICSetRSSv2SetCurrentProcessor( /*++ Routine Description: - This routine updates tracking information for the steering parameter + This routine updates tracking information for the steering parameter (Primary, Default or ITE[n]), as selected by the Command. Routine is called after the "move command" has fully succeeded. @@ -474,10 +474,10 @@ Return Value: VPort->RssV2Table[Command->IndirectionTableIndex] = NewProcessor; DEBUGP(MP_TRACE, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK: ITE[%d] VPortId %d, RssEnabled %d, TargetProc %d:%d\n", - Command->IndirectionTableIndex, - Command->VPortId, - VPort->RssEnabled, - NewProcessor.Group, + Command->IndirectionTableIndex, + Command->VPortId, + VPort->RssEnabled, + NewProcessor.Group, NewProcessor.Number); } } @@ -495,7 +495,7 @@ NICSetRSSv2ValidateCommandAndGetProcessor ( /*++ Routine Description: - This routine validates the move command, and returns information about + This routine validates the move command, and returns information about specified steering parameter (Primary, Default or ITE[n] if command is valid. Arguments: @@ -504,7 +504,7 @@ Arguments: Command - Move command used to update steering parameter - CurrentProcessor - Pointer which receives processor where steering + CurrentProcessor - Pointer which receives processor where steering parameter currenty points to. CurrentCpuIndex - Corresponding local index @@ -550,8 +550,8 @@ Return Value: } else { - DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid IndirectionTableIndex(%d) >= %d\n", - Command->IndirectionTableIndex, + DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid IndirectionTableIndex(%d) >= %d\n", + Command->IndirectionTableIndex, VPort->RssV2Params.NumberOfIndirectionTableEntries); } } @@ -572,7 +572,7 @@ NICSetRSSv2Parameters( /*++ Routine Description: - This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request. + This routine handles OID_GEN_RECEIVE_SCALE_PARAMETERS_V2 set request. Arguments: @@ -581,9 +581,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { USHORT EntryIndex; BOOLEAN IsHashInfoChanged; @@ -614,14 +614,14 @@ Return Value: // // Validate the request // - if (RssParams->HashSecretKeySize != + if (RssParams->HashSecretKeySize != NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid HashSecretKeySize\n"); return NDIS_STATUS_INVALID_LENGTH; } - if ((Set->InformationBufferLength < + if ((Set->InformationBufferLength < (RssParams->HashSecretKeyOffset + RssParams->HashSecretKeySize)) || (RssParams->HashSecretKeyOffset < @@ -633,7 +633,7 @@ Return Value: if ((NdisRequest->Flags & NDIS_OID_REQUEST_FLAGS_VPORT_ID_VALID) != 0) { - DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Issued for VPortId=%d, Flags=0x%x \n", + DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Issued for VPortId=%d, Flags=0x%x \n", NdisRequest->VPortId, RssParams->Flags); VPortId = NdisRequest->VPortId; } @@ -643,7 +643,7 @@ Return Value: VPortId = NDIS_INVALID_VPORT_ID; } - if ((VPortId != NDIS_INVALID_VPORT_ID) && + if ((VPortId != NDIS_INVALID_VPORT_ID) && (VPortId >= MAX_NIC_SWITCH_VPORTS)) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid VPortId\n"); @@ -659,23 +659,23 @@ Return Value: VPort = &Adapter->RSSData.NativeVPort; } - IsNumQueuesChanged = + IsNumQueuesChanged = ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_NUMBER_OF_QUEUES_CHANGED) != 0) && (RssParams->NumberOfQueues != VPort->RssV2Params.NumberOfQueues); - IsRssEnabled = + IsRssEnabled = ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_ENABLE_RSS) != 0); - IsNumITEsChanged = + IsNumITEsChanged = ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_NUMBER_OF_ENTRIES_CHANGED) != 0) && - (RssParams->NumberOfIndirectionTableEntries != + (RssParams->NumberOfIndirectionTableEntries != VPort->RssV2Params.NumberOfIndirectionTableEntries); - IsHashInfoChanged = + IsHashInfoChanged = ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_HASH_INFO_CHANGED) != 0) && (VPort->RssV2Params.HashInformation != RssParams->HashInformation); - IsHashKeyChanged = + IsHashKeyChanged = ((RssParams->Flags & NDIS_RECEIVE_SCALE_PARAM_HASH_KEY_CHANGED) != 0) && !RtlEqualMemory(&VPort->RssV2Key, (PUCHAR)RssParams + RssParams->HashSecretKeyOffset, @@ -700,7 +700,7 @@ Return Value: { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId=%d, NQ-Violation (queue change): NQueues=%d < NProcs=%d\n", NdisRequest->VPortId, - NewNumberOfQueues, + NewNumberOfQueues, NumProcs); Status = NDIS_STATUS_NO_QUEUES; goto Cleanup; @@ -730,9 +730,9 @@ Return Value: if ((ProcessorNumber.Group != VPort->RssV2Table[EntryIndex].Group) || (ProcessorNumber.Number != VPort->RssV2Table[EntryIndex].Number)) { - DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Cannot shrink IT size from %d to %d, mismatch at ITE[%d]\n", - NdisRequest->VPortId, - OldITCount, + DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Cannot shrink IT size from %d to %d, mismatch at ITE[%d]\n", + NdisRequest->VPortId, + OldITCount, NewITCount, EntryIndex); Status = NDIS_STATUS_INVALID_DATA; @@ -755,7 +755,7 @@ Return Value: &LocalCpuIndex)) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid DedfaultProcessorNumebr: %d:%d \n", - VPort->DefaultProcessorNumber.Group, + VPort->DefaultProcessorNumber.Group, VPort->DefaultProcessorNumber.Number); Status = NDIS_STATUS_INVALID_DATA; @@ -772,12 +772,12 @@ Return Value: ProcessorNumber = VPort->RssV2Table[EntryIndex]; if (!NICSetRSSv2ValidateRssProcessor(Adapter, - ProcessorNumber, + ProcessorNumber, &LocalCpuIndex)) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid ITE[%d]: %d:%d \n", EntryIndex, - ProcessorNumber.Group, + ProcessorNumber.Group, ProcessorNumber.Number); Status = NDIS_STATUS_INVALID_DATA; @@ -789,7 +789,7 @@ Return Value: } // - // After VPort->QueueMap is built, check for NQ-violation during + // After VPort->QueueMap is built, check for NQ-violation during // RSS enablement. // // Get number of queues after RSS enablement. @@ -798,7 +798,7 @@ Return Value: if (NumProcs > NewNumberOfQueues) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: NQ-Violation: NQueues=%d < NProcs=%d\n", - NewNumberOfQueues, + NewNumberOfQueues, NumProcs); Status = NDIS_STATUS_NO_QUEUES; goto Cleanup; @@ -813,11 +813,11 @@ Return Value: PrimaryProcessorNumber = VPort->PrimaryProcessorNumber; if (!NICSetRSSv2ValidateRssProcessor(Adapter, - PrimaryProcessorNumber, + PrimaryProcessorNumber, &LocalCpuIndex)) { DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: Invalid PrimaryProcessorNumebr: %d:%d \n", - PrimaryProcessorNumber.Group, + PrimaryProcessorNumber.Group, PrimaryProcessorNumber.Number); Status = NDIS_STATUS_INVALID_DATA; @@ -834,7 +834,7 @@ Return Value: // if (IsHashKeyChanged) { - VPort->RssV2Params.HashSecretKeySize = + VPort->RssV2Params.HashSecretKeySize = RssParams->HashSecretKeySize; NdisMoveMemory(&VPort->RssV2Key, @@ -857,7 +857,7 @@ Return Value: // // IT expansion // - DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Expand IT size from %d to %d\n", + DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Expand IT size from %d to %d\n", NdisRequest->VPortId, OldITCount, NewITCount); ASSERT((NewITCount % OldITCount) == 0); @@ -876,7 +876,7 @@ Return Value: // // IT contraction // - DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Shrink IT size from %d to %d\n", + DEBUGP(MP_ERROR, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId %d, Shrink IT size from %d to %d\n", NdisRequest->VPortId, OldITCount, NewITCount); ASSERT((OldITCount % NewITCount) == 0); @@ -893,20 +893,20 @@ Return Value: } // - // Apply new configuration to HW (hash key and information is already in + // Apply new configuration to HW (hash key and information is already in // the VPort object). // - MiniportApplyConfigurationToHW(Adapter, - VPort, + MiniportApplyConfigurationToHW(Adapter, + VPort, IsRssEnabled, - NewITCount, + NewITCount, NewNumberOfQueues); VPort->RssV2Params.NumberOfIndirectionTableEntries = NewITCount; VPort->RssV2Params.NumberOfQueues = NewNumberOfQueues; VPort->RssEnabled = IsRssEnabled; - DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId=%d, RssEnabled=%d, IT.size=%d\n", + DEBUGP(MP_TRACE, "OID_GEN_RECEIVE_SCALE_PARAMETERS_V2: VPortId=%d, RssEnabled=%d, IT.size=%d\n", NdisRequest->VPortId, IsRssEnabled, VPort->RssV2Params.NumberOfIndirectionTableEntries); Set->BytesNeeded = Set->InformationBufferLength; @@ -928,7 +928,7 @@ NICSetRSSv2IndirectionTableEntries( /*++ Routine Description: - This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request. + This routine handles OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES method request. Arguments: @@ -937,9 +937,9 @@ Arguments: Return Value: - NDIS_STATUS + NDIS_STATUS ---*/ +--*/ { PROCESSOR_NUMBER ActorProcessorNumber; PNDIS_RSS_SET_INDIRECTION_ENTRY Command; @@ -962,10 +962,10 @@ Return Value: PMP_ADAPTER_VPORT VPort; // - // Allocate a local queue map on stack, to hold temporary results during + // Allocate a local queue map on stack, to hold temporary results during // handling of each "move all" group. // - DECLARE_RSSV2_QUEUE_MAP_ON_STACK(LocalQueueMap, + DECLARE_RSSV2_QUEUE_MAP_ON_STACK(LocalQueueMap, RSSV2_MAX_NUMBER_OF_PROCESSORS_IN_RSS_TABLE); DEBUGP(MP_TRACE, "[%p] ---> NICSetRSSv2IndirectionTableEntries\n", Adapter); @@ -976,12 +976,12 @@ Return Value: Method->BytesRead = 0; Method->BytesNeeded = 0; - Method->BytesWritten = 0; + Method->BytesWritten = 0; // // Validate the request // - if (InputBufferLength < + if (InputBufferLength < (NDIS_SIZEOF_RSS_SET_INDIRECTION_ENTRIES_REVISION_1 + RssEntries->NumberOfRssEntries * RssEntries->RssEntrySize)) { @@ -993,7 +993,7 @@ Return Value: // // RSSv2 spec requires up to 130 entries to be handled in a single batch. // - if (RssEntries->NumberOfRssEntries > + if (RssEntries->NumberOfRssEntries > (2 + MAX_NUMBER_OF_INDIRECTION_TABLE_ENTRIES)) { DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid NumberOfRssEntries \n"); @@ -1011,8 +1011,8 @@ Return Value: ((PUCHAR)RssEntries + RssEntries->RssEntryTableOffset); DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Actor %d:%d, NumberOfRssEntries %d \n", - ActorProcessorNumber.Group, - ActorProcessorNumber.Number, + ActorProcessorNumber.Group, + ActorProcessorNumber.Number, RssEntries->NumberOfRssEntries); NumCommandsToExecute = 0; @@ -1034,18 +1034,18 @@ Return Value: { if (SwitchId != NDIS_DEFAULT_SWITCH_ID) { - DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid SwitchId (%d)\n", + DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid SwitchId (%d)\n", SwitchId); - RssV2SetCommandRangeStatus(&Context, + RssV2SetCommandRangeStatus(&Context, NDIS_STATUS_INVALID_PARAMETER); continue; // while (RssV2FindNextCommandRange()) } if (VPortId > MAX_NIC_SWITCH_VPORTS) { - DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid VPortId (%d)\n", + DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: Invalid VPortId (%d)\n", VPortId); - RssV2SetCommandRangeStatus(&Context, + RssV2SetCommandRangeStatus(&Context, NDIS_STATUS_INVALID_PARAMETER); continue; // while (RssV2FindNextCommandRange()) } @@ -1053,19 +1053,19 @@ Return Value: VPort = &Adapter->RSSData.VPort[VPortId]; if (VPort->Created == FALSE) - { - DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not created\n", + { + DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not created\n", VPortId); - RssV2SetCommandRangeStatus(&Context, + RssV2SetCommandRangeStatus(&Context, NDIS_STATUS_INVALID_PARAMETER); continue; // while (RssV2FindNextCommandRange()) } if (VPort->Active == FALSE) - { - DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not active\n", + { + DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPort %d is not active\n", VPortId); - RssV2SetCommandRangeStatus(&Context, + RssV2SetCommandRangeStatus(&Context, NDIS_STATUS_INVALID_PORT_STATE); continue; // while (RssV2FindNextCommandRange()) } @@ -1080,7 +1080,7 @@ Return Value: while ((Command = RssV2GetNextCommand(&Context, FALSE)) != NULL) { if (!NICSetRSSv2ValidateCommandAndGetProcessor( - VPort, + VPort, Command, &CurrentProcessorNumber, &OldCpuIndex, @@ -1094,12 +1094,12 @@ Return Value: (ActorProcessorNumber.Number != CurrentProcessorNumber.Number)) { DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPortId=%d, Flags=0x%x, EntryIndex=%d: Invalid Actor %d:%d, expected %d:%d\n", - Command->VPortId, + Command->VPortId, Command->Flags, - Command->IndirectionTableIndex, + Command->IndirectionTableIndex, ActorProcessorNumber.Group, ActorProcessorNumber.Number, - CurrentProcessorNumber.Group, + CurrentProcessorNumber.Group, CurrentProcessorNumber.Number); Command->EntryStatus = NDIS_STATUS_NOT_ACCEPTED; @@ -1116,9 +1116,9 @@ Return Value: (TargetProcessorNumber.Number == CurrentProcessorNumber.Number)) { DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: OK1: VPortId=%d, Flags=0x%x, EntryIndex=%d: TargetProc=%d:%d\n", - Command->VPortId, + Command->VPortId, Command->Flags, - Command->IndirectionTableIndex, + Command->IndirectionTableIndex, TargetProcessorNumber.Group, TargetProcessorNumber.Number); @@ -1132,16 +1132,16 @@ Return Value: // INACTIVE steering entities are only tracked and will be // enforced during RSS transition to ON/OFF. // - NICSetRSSv2SetCurrentProcessor(VPort, - Command, - TargetProcessorNumber, + NICSetRSSv2SetCurrentProcessor(VPort, + Command, + TargetProcessorNumber, 0xFF); DEBUGP(MP_ERROR, "NDIS_SET_INDIRECTION_TABLE_ENTRY: OK2: VPortId=%d, Flags=0x%x, EntryIndex=%d, TargetProc=%d:%d\n", - Command->VPortId, - Command->Flags, - Command->IndirectionTableIndex, - TargetProcessorNumber.Group, + Command->VPortId, + Command->Flags, + Command->IndirectionTableIndex, + TargetProcessorNumber.Group, TargetProcessorNumber.Number); Command->EntryStatus = NDIS_STATUS_SUCCESS; @@ -1149,7 +1149,7 @@ Return Value: } if (!NICSetRSSv2ValidateRssProcessor(Adapter, - TargetProcessorNumber, + TargetProcessorNumber, &NewCpuIndex)) { Command->EntryStatus = NDIS_STATUS_INVALID_DATA; @@ -1189,7 +1189,7 @@ Return Value: // // VPorts are already validated // - VPort = IsNativeRss ? &Adapter->RSSData.NativeVPort : + VPort = IsNativeRss ? &Adapter->RSSData.NativeVPort : &Adapter->RSSData.VPort[VPortId]; RssV2NQEnforcerEnter(VPort->QueueMap, LocalQueueMap); @@ -1201,7 +1201,7 @@ Return Value: { TargetProcessorNumber = Command->TargetProcessorNumber; IsValid = NICSetRSSv2ValidateRssProcessor(Adapter, - TargetProcessorNumber, + TargetProcessorNumber, &NewCpuIndex); ASSERT(IsValid); @@ -1216,12 +1216,12 @@ Return Value: } Status = RssV2NQEnforcerLeave(VPort->QueueMap, - LocalQueueMap, + LocalQueueMap, VPort->RssV2Params.NumberOfQueues); if (Status != NDIS_STATUS_SUCCESS) { DEBUGP(MP_ERROR, "OID_GEN_RSS_SET_INDIRECTION_TABLE_ENTRIES: VPortId=%d: NQ-violation: NQueues=%d < NProcs=%d\n", - VPortId, + VPortId, VPort->RssV2Params.NumberOfQueues, RssV2NQEnforcerGetNumberOfProcs(LocalQueueMap)); RssV2SetCommandRangeStatus(&Context, Status); @@ -1233,7 +1233,7 @@ Return Value: // // - // Iterate over the same Command range to actually update the + // Iterate over the same Command range to actually update the // processor numbers/indices. // RssV2RestartCommandIterator(&Context); @@ -1242,7 +1242,7 @@ Return Value: { TargetProcessorNumber = Command->TargetProcessorNumber; IsValid = NICSetRSSv2ValidateRssProcessor(Adapter, - TargetProcessorNumber, + TargetProcessorNumber, &NewCpuIndex); ASSERT(IsValid); @@ -1254,16 +1254,16 @@ Return Value: // // Reflect the change in software structure. // - NICSetRSSv2SetCurrentProcessor(VPort, - Command, - TargetProcessorNumber, + NICSetRSSv2SetCurrentProcessor(VPort, + Command, + TargetProcessorNumber, NewCpuIndex); DEBUGP(MP_ERROR, "NDIS_SET_INDIRECTION_TABLE_ENTRY: OK3: VPortId=%d, Flags=0x%x, EntryIndex=%d, TargetProc=%d:%d\n", - Command->VPortId, - Command->Flags, - Command->IndirectionTableIndex, - TargetProcessorNumber.Group, + Command->VPortId, + Command->Flags, + Command->IndirectionTableIndex, + TargetProcessorNumber.Group, TargetProcessorNumber.Number); Command->EntryStatus = NDIS_STATUS_SUCCESS; diff --git a/network/ndis/netvmini/6x/rssv2lib.c b/network/ndis/netvmini/6x/rssv2lib.c index a2bc5550..9bee9583 100644 --- a/network/ndis/netvmini/6x/rssv2lib.c +++ b/network/ndis/netvmini/6x/rssv2lib.c @@ -23,7 +23,7 @@ Abstract: #define PRAGMA_STRUCTURE_PADDED 4324 #define PRAGMA_NO_RETTYPE_FOR_FUNC 4508 #pragma warning(disable: PRAGMA_NO_RETTYPE_FOR_FUNC) -#pragma warning(disable: PRAGMA_ZERO_SIZED_ARRAY) +#pragma warning(disable: PRAGMA_ZERO_SIZED_ARRAY) #pragma warning(disable: PRAGMA_NAMELESS_STRUCT_UNION) #pragma warning(disable: PRAGMA_STRUCTURE_PADDED) #include <ndis.h> @@ -63,7 +63,7 @@ Return Value: Context->IsNativeRss = IsNativeRss; Context->RssV2Oid = RssV2Oid; Context->MaxIndex = RssV2Oid->NumberOfRssEntries; - Context->LimitIndex = 0; + Context->LimitIndex = 0; Context->StartIndex = 0; Context->LastStartIndex = 0; } @@ -182,14 +182,14 @@ RssV2GetNextCommand ( /*++ Routine Description: - This routine returns next command from the current command group (which - target the same SwitchId & VPortId). + This routine returns next command from the current command group (which + target the same SwitchId & VPortId). Arguments: Context - parsing context - SkipProcessedCommands - TRUE, if user wants to commands which already + SkipProcessedCommands - TRUE, if user wants to commands which already have EntryStatus changed from NDIS_STATUS_PENDING. FALSE, if user wants to iterate over all commands. @@ -205,14 +205,14 @@ Return Value: { if (Context->StartIndex < Context->LimitIndex) { - command = RSSV2_GET_COMMAND(Context->RssV2Oid, + command = RSSV2_GET_COMMAND(Context->RssV2Oid, Context->StartIndex++); } else { command = NULL; } - } while (SkipProcessedCommands && + } while (SkipProcessedCommands && (command != NULL) && (command->EntryStatus != NDIS_STATUS_PENDING)); @@ -289,7 +289,7 @@ RssV2NQEnforcerGetBitfield ( /*++ Routine Description: - Routine finds a pointer to the bitfield for specified + Routine finds a pointer to the bitfield for specified (RSS-)local processor index. Arguments: @@ -306,8 +306,8 @@ Return Value: { ASSERT(LocalCpuIndex < QueueMap->MaxProcessors); - return (PULONG_PTR)((PUINT8)QueueMap + - sizeof(RSSV2_QUEUE_MAP) + + return (PULONG_PTR)((PUINT8)QueueMap + + sizeof(RSSV2_QUEUE_MAP) + RSSV2_BITFIELD_OFFSET(LocalCpuIndex)); } @@ -320,7 +320,7 @@ RssV2NQEnforceGetReference ( /*++ Routine Description: - Routine finds a pointer to the reference counter for the specified + Routine finds a pointer to the reference counter for the specified (RSS-)local processor index. Arguments: @@ -337,8 +337,8 @@ Return Value: { ASSERT(LocalCpuIndex < QueueMap->MaxProcessors); - return (PUINT8)((PUINT8)QueueMap + - sizeof(RSSV2_QUEUE_MAP) + + return (PUINT8)((PUINT8)QueueMap + + sizeof(RSSV2_QUEUE_MAP) + RSSV2_BITFIELD_SIZE(QueueMap->MaxProcessors) + RSSV2_REFERENCE_OFFSET(LocalCpuIndex)); } @@ -387,7 +387,7 @@ Arguments: QueueMap - Pointer to the queue map - MaxNumberOfProcessorsInRssTable - Maximum number of processors which + MaxNumberOfProcessorsInRssTable - Maximum number of processors which RSS table can ever contain. Return Value: @@ -410,7 +410,7 @@ RssV2NQEnforcerReference ( /*++ Routine Description: - Routine marks processor as holding a reference. Corresponding bit in + Routine marks processor as holding a reference. Corresponding bit in the bitfiled is set to 1, and reference count is incremented. Arguments: @@ -448,7 +448,7 @@ RssV2NQEnforcerDereference ( Routine Description: Routine removes one reference cause by the processor. Reference count - is decremented, and if it becomes zero, a corresponding bit in + is decremented, and if it becomes zero, a corresponding bit in the bitfiled is cleared to 0. Arguments: @@ -482,7 +482,7 @@ Return Value: VOID RssV2NQEnforcerUpdate ( _Inout_ PRSSV2_QUEUE_MAP QueueMap, - _In_ UINT8 OldCpuIndex, + _In_ UINT8 OldCpuIndex, _In_ UINT8 NewCpuIndex ) /*++ @@ -540,8 +540,8 @@ Return Value: numberOfProcessors = 0; - for (localCpuIndex = 0; - localCpuIndex < QueueMap->MaxProcessors; + for (localCpuIndex = 0; + localCpuIndex < QueueMap->MaxProcessors; localCpuIndex += BITS_PER_WORD) { bitfield = RssV2NQEnforcerGetBitfield(QueueMap, localCpuIndex); @@ -576,9 +576,9 @@ Return Value: --*/ { KeAcquireSpinLockAtDpcLevel(&GlobalQueueMap->SpinLock); - - RtlMoveMemory(LocalQueueMap, - GlobalQueueMap, + + RtlMoveMemory(LocalQueueMap, + GlobalQueueMap, RssV2NQEnforcerGetQueueMapSize(GlobalQueueMap->MaxProcessors)); } @@ -616,9 +616,9 @@ Routine Description: Arguments: GlobalQueueMap - Pointer to the global queue map (e.g. VPort's) visible by - many processors. + many processors. - LocalQueueMap - Pointer to the queue map on stack. If NQ-check succeeds, + LocalQueueMap - Pointer to the queue map on stack. If NQ-check succeeds, the global queue map will be updated from the local copy. If NQ-check fails, local copy will be discarded and global copy is unchanged. @@ -627,10 +627,10 @@ Arguments: Return Value: - NDIS_STATUS_SUCCESS - if the accumulated local changes lead to valid + NDIS_STATUS_SUCCESS - if the accumulated local changes lead to valid configuration. - - NDIS_STATUS_NO_QUEUES - if the accumulated local configuration exceeds + + NDIS_STATUS_NO_QUEUES - if the accumulated local configuration exceeds QueueLimit. --*/ @@ -639,8 +639,8 @@ Return Value: if (RssV2NQEnforcerGetNumberOfProcs(LocalQueueMap) <= QueueLimit) { - RtlMoveMemory(GlobalQueueMap, - LocalQueueMap, + RtlMoveMemory(GlobalQueueMap, + LocalQueueMap, RssV2NQEnforcerGetQueueMapSize(GlobalQueueMap->MaxProcessors)); status = NDIS_STATUS_SUCCESS; diff --git a/network/ndis/netvmini/6x/rssv2lib.h b/network/ndis/netvmini/6x/rssv2lib.h index 619624ec..9a867a57 100644 --- a/network/ndis/netvmini/6x/rssv2lib.h +++ b/network/ndis/netvmini/6x/rssv2lib.h @@ -26,7 +26,7 @@ Revision History: // #if !defined(NDIS_STATUS_NO_QUEUES) #define NDIS_STATUS_NO_QUEUES 0xC0230031L -#endif +#endif #ifdef __cplusplus extern "C" @@ -98,7 +98,7 @@ RssV2SetCommandRangeStatus ( // // Queue map for VPort (or for adapter's in NativeRSS mode) -// +// #define BITS_PER_WORD (sizeof(ULONG_PTR) * 8) #define RSSV2_BITFIELD_OFFSET(_PROC_INDEX_) ((_PROC_INDEX_) / BITS_PER_WORD) #define RSSV2_BITFIELD_SIZE(_MAX_PROC_) \ @@ -112,7 +112,7 @@ typedef struct _RSSV2_QUEUE_MAP // // Members to help enforce "NQ-violation" (per-VPort limit on number of queues) // - KSPIN_LOCK SpinLock; + KSPIN_LOCK SpinLock; // // Maximum number of processors in adapter's RSS table. @@ -124,7 +124,7 @@ typedef struct _RSSV2_QUEUE_MAP // Two variable-size fields follow this structure: // // - Bitmask of referenced processors - // - Array with reference counts for each RSS processor + // - Array with reference counts for each RSS processor // (indexed by a local CPU index, which is relative to RSS table). // // @@ -140,12 +140,12 @@ typedef struct _RSSV2_QUEUE_MAP (PRSSV2_QUEUE_MAP)_alloca(RssV2NQEnforcerGetQueueMapSize(_MAX_PROCS_)) FORCEINLINE -ULONG +ULONG RssV2NQEnforcerGetQueueMapSize ( _In_ ULONG MaxNumberOfProcessorsInRssTable ) { - return sizeof(RSSV2_QUEUE_MAP) + + return sizeof(RSSV2_QUEUE_MAP) + RSSV2_BITFIELD_SIZE(MaxNumberOfProcessorsInRssTable) + RSSV2_REFERENCE_SIZE(MaxNumberOfProcessorsInRssTable); } @@ -176,7 +176,7 @@ RssV2NQEnforcerDereference ( VOID RssV2NQEnforcerUpdate ( _Inout_ PRSSV2_QUEUE_MAP QueueMap, - _In_ UINT8 OldCpuIndex, + _In_ UINT8 OldCpuIndex, _In_ UINT8 NewCpuIndex ); diff --git a/network/ndis/netvmini/6x/tcbrcb.c b/network/ndis/netvmini/6x/tcbrcb.c index 1d2faf50..1cbeb673 100644 --- a/network/ndis/netvmini/6x/tcbrcb.c +++ b/network/ndis/netvmini/6x/tcbrcb.c @@ -111,7 +111,7 @@ Return Value: { // // The adapter is no longer in a ready state, so we were not able to take a reference on the - // receive block. Add the RCB back to the free list and fail this receive. + // receive block. Add the RCB back to the free list and fail this receive. // NdisInterlockedInsertTailList( &Adapter->FreeRcbList, @@ -136,14 +136,14 @@ Return Value: // if(Status == NDIS_STATUS_RESOURCES) { - ++Adapter->RxResourceErrors; + ++Adapter->RxResourceErrors; } else if(Status != NDIS_STATUS_INVALID_ADDRESS) { ++Adapter->RxRuntErrors; } // - // Recover RCB + // Recover RCB // ReturnRCB(Adapter, Rcb); Rcb = NULL; @@ -186,7 +186,7 @@ Return Value: --*/ { PUCHAR Data = Rcb->Data; - ASSERT(Data); + ASSERT(Data); DEBUGP(MP_TRACE, "[%p] ---> ReturnRCB. RCB: %p\n", Adapter, Rcb); diff --git a/network/ndis/netvmini/6x/tcbrcb.h b/network/ndis/netvmini/6x/tcbrcb.h index fca8f123..78f8b5ca 100644 --- a/network/ndis/netvmini/6x/tcbrcb.h +++ b/network/ndis/netvmini/6x/tcbrcb.h @@ -57,7 +57,7 @@ typedef struct _RCB LIST_ENTRY RcbLink; PNET_BUFFER_LIST Nbl; PVOID Data; -#if (NDIS_SUPPORT_NDIS620) +#if (NDIS_SUPPORT_NDIS620) PVOID LookaheadData; #endif } RCB, *PRCB; diff --git a/network/ndis/netvmini/6x/trace.h b/network/ndis/netvmini/6x/trace.h index b42c5275..b8adbd2e 100644 --- a/network/ndis/netvmini/6x/trace.h +++ b/network/ndis/netvmini/6x/trace.h @@ -14,7 +14,7 @@ Module Name: Abstract: - --*/ +--*/ #ifndef _TRACE_H diff --git a/network/ndis/netvmini/6x/vmq.c b/network/ndis/netvmini/6x/vmq.c index d4e8fa7c..71c561bb 100644 --- a/network/ndis/netvmini/6x/vmq.c +++ b/network/ndis/netvmini/6x/vmq.c @@ -325,7 +325,7 @@ Return Value: #if (NDIS_SUPPORT_NDIS630) HwCapabilities.SupportedQueueProperties |= NDIS_RECEIVE_FILTER_DYNAMIC_PROCESSOR_AFFINITY_CHANGE_SUPPORTED; #endif - + HwCapabilities.SupportedFilterTests = NDIS_RECEIVE_FILTER_TEST_HEADER_FIELD_EQUAL_SUPPORTED; HwCapabilities.SupportedHeaders = NDIS_RECEIVE_FILTER_MAC_HEADER_SUPPORTED; HwCapabilities.SupportedMacHeaderFields = NDIS_RECEIVE_FILTER_MAC_HEADER_DEST_ADDR_SUPPORTED | NDIS_RECEIVE_FILTER_MAC_HEADER_VLAN_ID_SUPPORTED; @@ -3104,7 +3104,7 @@ Routine Description: Arguments: Adapter - Pointer to our adapter - Rcb - RCB to queue for recieve + Rcb - RCB to queue for receive Return Value: diff --git a/network/ndis/netvmini/6x/vmq.h b/network/ndis/netvmini/6x/vmq.h index 5b949e2a..98224c02 100644 --- a/network/ndis/netvmini/6x/vmq.h +++ b/network/ndis/netvmini/6x/vmq.h @@ -13,7 +13,7 @@ Module Name: Abstract: - This module declares the VMQ related data types, flags, macros, and functions. + This module declares the VMQ related data types, flags, macros, and functions. Revision History: @@ -24,7 +24,7 @@ Notes: struct _FRAME; struct _RCB; - + #if (NDIS_SUPPORT_NDIS620) @@ -65,8 +65,8 @@ typedef struct _MP_ADAPTER_SHARED_MEMORY } MP_ADAPTER_SHARED_MEMORY, *PMP_ADAPTER_SHARED_MEMORY; // -// The minimum number of shared memory blocks we require. Used when recovering from -// shared memory allocation failures. +// The minimum number of shared memory blocks we require. Used when recovering from +// shared memory allocation failures. // #define NIC_MIN_RECV_ENTRY_ALLOCATION_COUNT 32 @@ -75,20 +75,20 @@ typedef struct _MP_ADAPTER_SHARED_MEMORY // lock. // // -// The queue is initialized, but not yet completed. Receives disabled. +// The queue is initialized, but not yet completed. Receives disabled. // #define fMPAQI_INITIALIZED 0x1 // -// Completion of the queue has started. Receives disabled. +// Completion of the queue has started. Receives disabled. // #define fMPAQI_COMPLETION_STARTED 0x2 // -// Queue completed. Receives enabled. +// Queue completed. Receives enabled. // #define fMPAQI_COMPLETION_FINISHED 0x4 // -// Queue is being freed (pending RefCount). Receives disabled. -// +// Queue is being freed (pending RefCount). Receives disabled. +// #define fMPAQI_FREEING 0x8 // // DMA is being performed for queue @@ -153,7 +153,7 @@ typedef struct DECLSPEC_CACHEALIGN _MP_ADAPTER_QUEUE // PUCHAR RcbMemoryBlock; NDIS_HANDLE RecvNblPoolHandle; - + // // Shared memory information (MP_ADAPTER_SHARED_MEMORY) // @@ -164,12 +164,12 @@ typedef struct DECLSPEC_CACHEALIGN _MP_ADAPTER_QUEUE LIST_ENTRY LookaheadSharedMemoryList; LIST_ENTRY PostLookaheadSharedMemoryList; // - // MP_ADAPTER_SHARED_MEMORY_BLOCK buffers to hold book-keeping info on subdivided shared memory buffers + // MP_ADAPTER_SHARED_MEMORY_BLOCK buffers to hold book-keeping info on subdivided shared memory buffers // PUCHAR LookaheadBlocks; ULONG NumLookaheadBlocks; - PUCHAR PostLookaheadBlocks; - ULONG NumPostLookaheadBlocks; + PUCHAR PostLookaheadBlocks; + ULONG NumPostLookaheadBlocks; // // Data passed in through the VMQ Queue configuration related OIDs @@ -187,7 +187,7 @@ typedef struct DECLSPEC_CACHEALIGN _MP_ADAPTER_QUEUE typedef struct _MP_ADAPTER_FILTER { // - // Whether the receive filter should be used + // Whether the receive filter should be used // BOOLEAN Valid; // @@ -214,11 +214,11 @@ typedef struct _MP_ADAPTER_FILTER // #define fMPVMQD_FILTERING_ENABLED 0x0001 // -// Lookahead split in VMQ indication is enabled on the adapter. +// Lookahead split in VMQ indication is enabled on the adapter. // #define fMPVMQD_LOOKAHEAD_ENABLED 0x0002 // -// VLAN filtering in VMQ is enabled on the adapter. +// VLAN filtering in VMQ is enabled on the adapter. // #define fMPVMQD_VLANFILTER_ENABLED 0x0004 @@ -237,7 +237,7 @@ typedef struct _MP_ADAPTER_FILTER // // The MP_ADAPTER_VMQ_DATA structure is used to track the global VMQ configuration for an adapter -// +// typedef struct _MP_ADAPTER_VMQ_DATA { // @@ -246,7 +246,7 @@ typedef struct _MP_ADAPTER_VMQ_DATA ULONG Flags; // // Individual Queues. The MP_ADAPTER_QUEUE array is not dynamically allocated to reduce - // pointer dereferencing during receives, which can affect performance. + // pointer dereferencing during receives, which can affect performance. // MP_ADAPTER_QUEUE RxQueues[NIC_SUPPORTED_NUM_QUEUES]; // @@ -263,7 +263,7 @@ VOID FreeVMQData( _Inout_ struct _MP_ADAPTER *Adapter); -NDIS_STATUS +NDIS_STATUS ReadRxQueueConfig( _In_ NDIS_HANDLE ConfigurationHandle, _Inout_ struct _MP_ADAPTER *Adapter); @@ -315,7 +315,7 @@ SetRxFilter( ); NDIS_STATUS -ClearRxFilter( +ClearRxFilter( _Inout_ struct _MP_ADAPTER *Adapter, _In_ PNDIS_RECEIVE_FILTER_CLEAR_PARAMETERS FilterParams ); @@ -346,16 +346,16 @@ GetRcbForRxQueue( _In_ PNDIS_NET_BUFFER_LIST_8021Q_INFO Nbl1QInfo, _Outptr_result_maybenull_ struct _RCB **Rcb); -NDIS_STATUS +NDIS_STATUS CopyFrameToRxQueueRcb( _In_ struct _MP_ADAPTER *Adapter, _In_ struct _FRAME *Frame, _In_ PNDIS_NET_BUFFER_LIST_8021Q_INFO Nbl1QInfo, _Inout_ struct _RCB *Rcb, _Out_ BOOLEAN *Copied); - + VOID -RecoverRxQueueRcb( +RecoverRxQueueRcb( _In_ struct _MP_ADAPTER *Adapter, _In_ struct _RCB *Rcb); @@ -369,10 +369,10 @@ AddPendingRcbToRxQueue( #else // -// In order to avoid excessible "#if defined(NDIS620_MINIPORT)" statements scattered -// through the miniport implementation, NDIS60 miniports define -// placeholder macros for the VMQ functions which cause the code to always proceed -// as if VMQ were disabled on the adapter. +// In order to avoid excessible "#if defined(NDIS620_MINIPORT)" statements scattered +// through the miniport implementation, NDIS60 miniports define +// placeholder macros for the VMQ functions which cause the code to always proceed +// as if VMQ were disabled on the adapter. // #define VMQ_ENABLED(_Adapter) FALSE @@ -380,7 +380,7 @@ AddPendingRcbToRxQueue( #define VLAN_FILTER_ENABLED(_Adapter) FALSE #define LOOKAHEAD_SPLIT_REQUIRED(_QueueInfo) FALSE #define AllocateDefaultRxQueue(Adapter) NDIS_STATUS_NOT_SUPPORTED -#define AddPendingRcbToRxQueue(Adapter, Rcb) +#define AddPendingRcbToRxQueue(Adapter, Rcb) #define GetRxQueueDpc(Adapter, QueueId) NULL #define AllocateVMQData(Adapter) NDIS_STATUS_SUCCESS #define FreeVMQData(Adapter) @@ -388,6 +388,6 @@ AddPendingRcbToRxQueue( #define InitializeRxQueueMPConfig(Adapter) NDIS_STATUS_SUCCESS #define CopyFrameToRxQueueRcb(Adapter, Frame, Nbl1QInfo, Rcb, Copied) FALSE #define GetRcbForRxQueue(Adapter, Frame, Nbl1QInfo, Rcb) NDIS_STATUS_NOT_SUPPORTED -#define RecoverRxQueueRcb(Adapter, Rcb) +#define RecoverRxQueueRcb(Adapter, Rcb) #endif diff --git a/network/netadaptercx/netvadapter/README.md b/network/netadaptercx/netvadapter/README.md new file mode 100644 index 00000000..894f5e40 --- /dev/null +++ b/network/netadaptercx/netvadapter/README.md @@ -0,0 +1,113 @@ +--- +page_type: sample +description: "A virtual NIC (NetAdapterCx) miniport driver built on top of netvadapterlibrary, in both KMDF and UMDF flavors." +languages: +- cpp +products: +- windows +- windows-wdk +--- + +# netvadapter — Virtual NIC Sample + +`netvadapter` is a **virtual Ethernet NIC** driver that uses **NetAdapterCx** for its data +path. It links against the shared **netvadapterlibrary** static library (the same library used +by the WIFICX sample) and ships in both **KMDF** and **UMDF** flavors. + +Two `netvadapter` instances can be paired together through the library's **Emulated Network +Link (ENL)**: packets sent on one adapter are delivered to the other and vice‑versa, so you can +run connectivity tests (ping, throughput) entirely in software with no physical hardware. + +--- + +## Layout + +| Path | Description | +| --- | --- | +| `netvadapter.sln` | Solution containing both drivers + the library project references. | +| `build.cmd` | Build wrapper (see **Building** — pins UMDF to 2.33). | +| `km\netvadapterkm.vcxproj` | KMDF driver → `netvadapter.sys` (INF: `km\netvadapter.inf`). | +| `um\netvadapterum.vcxproj` | UMDF driver → `netvadapterum.dll` (INF: `um\netvadapterum.inf`). | +| `drivercode\` | Shared driver source (see below). | + +## Building + +The UMDF driver targets **UMDF 2.33** (to match `netvadapterum.inf`'s +`UmdfLibraryVersion = 2.33.0`), while the shared `netvadapterlibrary` is checked in at **UMDF +2.35** (so the WIFICX sample is unaffected). Because the WDF version must match within a single +binary, **build through `build.cmd`**, which forces the library and driver to 2.33 for this +solution only: + +```cmd +build.cmd :: Debug x64 (defaults) +build.cmd Release x64 +``` + +> A plain `msbuild netvadapter.sln` or a Visual Studio IDE build will fail to link with an +> unresolved `WdfFunctions_02035` symbol, because it does not apply the 2.33 override. + +### Signing the package (test signing) + +The build signs the binaries but does **not** produce a catalog. To create and test‑sign the +catalogs (required to install while in test‑signing mode): + +```cmd +:: From an EWDK environment, for each package folder under x64\<Config>\: +Inf2Cat /driver:.\netvadapterkm /os:10_X64,Server10_X64 +Inf2Cat /driver:.\netvadapterum /os:10_X64,Server10_X64 + +signtool sign /fd SHA256 /sha1 <WDKTestCertThumbprint> /tr http://timestamp.digicert.com /td SHA256 .\netvadapterkm\netvadapter.cat +signtool sign /fd SHA256 /sha1 <WDKTestCertThumbprint> /tr http://timestamp.digicert.com /td SHA256 .\netvadapterum\netvadapterum.cat +``` + +--- + +## Installing + +Enable test signing once (elevated, then reboot), and install the test certificate into the +**Root** and **TrustedPublisher** stores on the target machine. Then install the driver with +`devcon`: + +```cmd +.\devcon.exe install .\netvadapterum.inf root\netvadapterum +``` + +If the command fails, inspect the device‑install log at: + +``` +C:\Windows\INF\setupapi.dev.log +``` + +### Pairing two adapters + +A working link requires **two** `netvadapter` instances. Create both by running the install +command **twice**: + +```cmd +.\devcon.exe install .\netvadapterum.inf root\netvadapterum +.\devcon.exe install .\netvadapterum.inf root\netvadapterum +``` + +Then set the **`MACLastByte`** advanced keyword to 1 and 2 on both adapters via Device Manager → adapter → **Advanced**, or the network adapter +property pages. + +> ⚠️ `MACLastByte` defaults to **0**. If an adapter is left at the default, the device fails +> to start and shows a **yellow bang** (error) in Device Manager. Assign distinct values such as +> `1` and `2` for the pair to link correctly. + +--- + +## Managing the driver + +List installed `net`‑class drivers (to find the `oemNN.inf` published name): + +```cmd +pnputil /enum-drivers /class net +``` + +Remove the driver and prepare for a clean reinstall (substitute the `oemNN.inf` from the command +above): + +```cmd +pnputil /delete-driver oem2.inf /uninstall /force +``` diff --git a/network/netadaptercx/netvadapter/build.cmd b/network/netadaptercx/netvadapter/build.cmd new file mode 100644 index 00000000..3f7c8e5d --- /dev/null +++ b/network/netadaptercx/netvadapter/build.cmd @@ -0,0 +1,25 @@ +@echo off +REM ============================================================================ +REM Build wrapper for netvadapter.sln +REM +REM The netvadapter UM driver targets UMDF 2.33 (matching netvadapterum.inf's +REM UmdfLibraryVersion = 2.33.0). It links the shared netvadapterlibrary, whose +REM checked-in project targets UMDF 2.35 (so the wificx sample is unaffected). +REM +REM WDF version must match within a single binary, so this script forces the +REM library + driver to 2.33 *for this solution's build only* via a global +REM MSBuild property. A plain "msbuild netvadapter.sln" (without these props) +REM will fail to link with an unresolved WdfFunctions_02035 symbol. +REM +REM Usage: build.cmd [Configuration] [Platform] (defaults: Debug x64) +REM Example: build.cmd Release x64 +REM ============================================================================ + +setlocal +set CONFIG=%~1 +set PLAT=%~2 +if "%CONFIG%"=="" set CONFIG=Debug +if "%PLAT%"=="" set PLAT=x64 + +msbuild "%~dp0netvadapter.sln" /t:Build /p:Configuration=%CONFIG% /p:Platform=%PLAT% /p:UMDF_VERSION_MINOR=33 /p:UMDF_MINIMUM_VERSION_REQUIRED=33 /m +endlocal diff --git a/network/netadaptercx/netvadapter/drivercode/device.cpp b/network/netadaptercx/netvadapter/drivercode/device.cpp new file mode 100644 index 00000000..6cbad327 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/device.cpp @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <wil/resource.h> + +#include "netvadapter.h" +#include "device.h" +#include "trace.h" +#include "device.tmh" +#include "power.h" + +static +EVT_NET_ADAPTER_CREATE_TXQUEUE + EvtAdapterCreateTxQueue; + +static +EVT_NET_ADAPTER_CREATE_RXQUEUE + EvtAdapterCreateRxQueue; + +NetvDevice::NetvDevice( + WDFDEVICE Handle +) + : m_triage(WdfGetTriageInfo()) + , m_handle(Handle) +{ +} + +_Use_decl_annotations_ +NTSTATUS +NetvDevice::Initialize( + void +) +{ + using unique_adapterinit = wil::unique_any<NETADAPTER_INIT*, + decltype(&::NetAdapterInitFree), + ::NetAdapterInitFree>; + + unique_adapterinit adapterInit{NetAdapterInitAllocate(m_handle)}; + RETURN_NTSTATUS_IF( + STATUS_INSUFFICIENT_RESOURCES, + ! adapterInit); + + NET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks; + NET_ADAPTER_DATAPATH_CALLBACKS_INIT( + &datapathCallbacks, + EvtAdapterCreateTxQueue, + EvtAdapterCreateRxQueue); + + NetAdapterInitSetDatapathCallbacks( + adapterInit.get(), + &datapathCallbacks); + + WDF_OBJECT_ATTRIBUTES adapterAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&adapterAttributes, NetvAdapter); + adapterAttributes.EvtDestroyCallback = [](WDFOBJECT Handle) { + NetvAdapterGetContext(static_cast<NETADAPTER>(Handle))->Destroy(); + }; + + NETADAPTER netAdapter; + RETURN_IF_NOT_STATUS_SUCCESS( + NetAdapterCreate(adapterInit.get(), &adapterAttributes, &netAdapter)); + + m_adapter = new (NetvAdapterGetContext(netAdapter)) NetvAdapter(netAdapter, m_handle); + + RETURN_IF_NOT_STATUS_SUCCESS( + m_adapter->Initialize()); + + RETURN_STATUS_SUCCESS(); +} + +NTSTATUS +NetvDevice::PrepareHardware( + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated +) +{ + UNREFERENCED_PARAMETER(ResourcesRaw); + UNREFERENCED_PARAMETER(ResourcesTranslated); + + NetvDeviceInitializePowerManagement(this); + + RETURN_IF_NOT_STATUS_SUCCESS( + m_adapter->ConfigureDataCapabilities()); + + RETURN_IF_NOT_STATUS_SUCCESS( + NetAdapterStart(m_adapter->m_handle)); + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +NTSTATUS +EvtDevicePrepareHardware( + WDFDEVICE Device, + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated + ) +{ + return NetvDeviceGetContext(Device)->PrepareHardware(ResourcesRaw, ResourcesTranslated); +} + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateTxQueue( + NETADAPTER Adapter, + NETTXQUEUE_INIT * Init +) +{ + return NetvAdapterGetContext(Adapter)->CreateTxQueue(Init); +} + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateRxQueue( + NETADAPTER Adapter, + NETRXQUEUE_INIT * Init +) +{ + return NetvAdapterGetContext(Adapter)->CreateRxQueue(Init); +} + +NetvAdapter* NetvAdapterGetContextFromWDFObject(NETADAPTER netAdapter) +{ + return NetvAdapterGetContext(netAdapter); +} diff --git a/network/netadaptercx/netvadapter/drivercode/device.h b/network/netadaptercx/netvadapter/drivercode/device.h new file mode 100644 index 00000000..3b8e5d2d --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/device.h @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#pragma once + +#include "netvadapter.h" + +class NetvDevice +{ + +public: + + // + // Do not add variable before WdfTriageInfoPtr. + // NetAdapterCx carving code requires the first field of + // WDF context to be a pointer to WDF_TRIAGE_INFO. + // + void * + m_triage = nullptr; + + NetvDevice( + WDFDEVICE Handle + ); + + NTSTATUS + Initialize( + void + ); + + NTSTATUS + PrepareHardware( + WDFCMRESLIST ResourcesRaw, + WDFCMRESLIST ResourcesTranslated + ); + +public: // private: + + WDFDEVICE + m_handle = WDF_NO_HANDLE; + + NetvAdapter * + m_adapter = nullptr; + +}; +static_assert(FIELD_OFFSET(NetvDevice, m_triage) == 0u); + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvDevice, NetvDeviceGetContext); +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvAdapter, NetvAdapterGetContext); + +EVT_WDF_DEVICE_PREPARE_HARDWARE + EvtDevicePrepareHardware; diff --git a/network/netadaptercx/netvadapter/drivercode/driver.cpp b/network/netadaptercx/netvadapter/drivercode/driver.cpp new file mode 100644 index 00000000..393292c1 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/driver.cpp @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <wil/resource.h> + +#include "netvadapter.h" +#include "trace.h" +#include "driver.tmh" +#include "device.h" +#include "power.h" + +GLOBAL_CONTEXT NetvGlobalContext; + +EXTERN_C +DRIVER_INITIALIZE + DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; +EVT_WDF_DRIVER_UNLOAD EvtDriverUnload; + +_Use_decl_annotations_ +NTSTATUS +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) +{ + WPP_INIT_TRACING(DriverObject, RegistryPath); + + WDF_DRIVER_CONFIG config; + WDF_DRIVER_CONFIG_INIT(&config, EvtDriverDeviceAdd); + config.EvtDriverUnload = EvtDriverUnload; + + NTSTATUS status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &config, + NULL); + + if (!NT_SUCCESS(status)) + { + LogError(FLAG_DRIVER, "%!STATUS! WdfDriverCreate", status); + WPP_CLEANUP(DriverObject); + + return status; + } + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +NTSTATUS +EvtDriverDeviceAdd( + WDFDRIVER Driver, + PWDFDEVICE_INIT DeviceInit + ) +{ + UNREFERENCED_PARAMETER(Driver); + + RETURN_IF_NOT_STATUS_SUCCESS( + NetDeviceInitConfig(DeviceInit)); + + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks; + WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks); + powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = EvtDeviceArmWakeFromS0; + powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = EvtDeviceDisarmWakeFromS0; + WdfDeviceInitSetPowerPolicyEventCallbacks(DeviceInit, &powerPolicyCallbacks); + + WDF_OBJECT_ATTRIBUTES deviceAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, NetvDevice); + + WDFDEVICE wdfDevice; + RETURN_IF_NOT_STATUS_SUCCESS( + WdfDeviceCreate(&DeviceInit, &deviceAttributes, &wdfDevice)); + + auto device = new (NetvDeviceGetContext(wdfDevice)) NetvDevice(wdfDevice); + + RETURN_IF_NOT_STATUS_SUCCESS( + device->Initialize()); + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +VOID +EvtDriverUnload( + WDFDRIVER Driver +) +{ + UNREFERENCED_PARAMETER(Driver); + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); +} diff --git a/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp b/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp new file mode 100644 index 00000000..29a2006a --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/memorymanagement.cpp @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +// +// Global operator new / delete for the driver. +// +// The shared netvadapterlibrary routes its allocations through the global +// operator new (see memory.cpp in the library, which provides the nothrow +// variant that forwards to operator new(size_t)). The client driver is +// responsible for providing the backing implementation. We use WDF managed +// memory so that the same implementation works for both KMDF and UMDF, the +// same approach used by the WIFICX sample. + +#include "pch.hpp" + +#define NETV_POOL_TAG 'vteN' + +struct NETV_MEMORY_HEADER +{ + size_t HeaderSize; + WDFMEMORY WdfMemoryHandle; +}; + +static void* AllocateBuffer(size_t Size) +{ + const size_t totalSize = Size + sizeof(NETV_MEMORY_HEADER); + + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + + WDFMEMORY wdfMemory = WDF_NO_HANDLE; + void* buffer = nullptr; + + if (!NT_SUCCESS(WdfMemoryCreate(&attributes, NonPagedPoolNx, NETV_POOL_TAG, totalSize, &wdfMemory, &buffer))) + { + return nullptr; + } + + RtlZeroMemory(buffer, totalSize); + + auto header = static_cast<NETV_MEMORY_HEADER*>(buffer); + header->HeaderSize = sizeof(NETV_MEMORY_HEADER); + header->WdfMemoryHandle = wdfMemory; + + return reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(buffer) + sizeof(NETV_MEMORY_HEADER)); +} + +static void FreeBuffer(void* Buffer) +{ + if (Buffer == nullptr) + { + return; + } + + auto header = reinterpret_cast<NETV_MEMORY_HEADER*>( + reinterpret_cast<ULONG_PTR>(Buffer) - sizeof(NETV_MEMORY_HEADER)); + + NT_ASSERT(header->HeaderSize == sizeof(NETV_MEMORY_HEADER)); + + WdfObjectDelete(header->WdfMemoryHandle); +} + +void* __cdecl operator new(size_t Size) +{ + return AllocateBuffer(Size); +} + +void* __cdecl operator new[](size_t Size) +{ + return AllocateBuffer(Size); +} + +void __cdecl operator delete(void* Buffer) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete[](void* Buffer) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete(void* Buffer, size_t) noexcept +{ + FreeBuffer(Buffer); +} + +void __cdecl operator delete[](void* Buffer, size_t) noexcept +{ + FreeBuffer(Buffer); +} diff --git a/network/netadaptercx/netvadapter/drivercode/pch.hpp b/network/netadaptercx/netvadapter/drivercode/pch.hpp new file mode 100644 index 00000000..b0e017ef --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/pch.hpp @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +#include <initguid.h> + +#ifdef _KERNEL_MODE +#include <ntddk.h> +#else +#include <windows.h> +#include <new> +#endif + +#include <wdf.h> +#include <netadaptercx.h> diff --git a/network/netadaptercx/netvadapter/drivercode/power.cpp b/network/netadaptercx/netvadapter/drivercode/power.cpp new file mode 100644 index 00000000..68b057ff --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/power.cpp @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" +#include "netvadapter.h" +#include "device.h" +#include "trace.h" +#include "power.h" +#include "power.tmh" + +void +NetvDeviceInitializePowerManagement( + _In_ NetvDevice * Device +) +{ +#ifdef _KERNEL_MODE + WDFDEVICE wdfDevice = Device->m_handle; + NetvAdapter * adapter = Device->m_adapter; + + if (!adapter->S0Idle) + { + return; + } + + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT( + &idleSettings, + IdleCanWakeFromS0); + + idleSettings.IdleTimeout = 3000; + idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; + + NTSTATUS ntStatus = WdfDeviceAssignS0IdleSettings( + wdfDevice, + &idleSettings); + + if (ntStatus != STATUS_SUCCESS) + { + // MSDN says we should ignore error codes from assign S0 idle settings, do that + return; + } + + // Now tell NetAdapterCx we support wake on packet filter match + NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES wakeOnPacketFilterMatch; + NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES_INIT(&wakeOnPacketFilterMatch); + wakeOnPacketFilterMatch.PacketFilterMatch = TRUE; + + NetAdapterWakeSetPacketFilterCapabilities(adapter->m_handle, &wakeOnPacketFilterMatch); +#else + UNREFERENCED_PARAMETER(Device); +#endif +} + +_Use_decl_annotations_ +NTSTATUS +EvtDeviceArmWakeFromS0( + WDFDEVICE Device +) +{ + auto adapter = NetvDeviceGetContext(Device)->m_adapter; + adapter->ArmWakeFromS0(); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +void +EvtDeviceDisarmWakeFromS0( + WDFDEVICE Device +) +{ + auto adapter = NetvDeviceGetContext(Device)->m_adapter; + adapter->DisarmWakeFromS0(); +} diff --git a/network/netadaptercx/netvadapter/drivercode/power.h b/network/netadaptercx/netvadapter/drivercode/power.h new file mode 100644 index 00000000..6a5e2399 --- /dev/null +++ b/network/netadaptercx/netvadapter/drivercode/power.h @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +EVT_WDF_DEVICE_ARM_WAKE_FROM_S0 EvtDeviceArmWakeFromS0; +EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0 EvtDeviceDisarmWakeFromS0; + +void +NetvDeviceInitializePowerManagement( + _In_ NetvDevice * Device +); diff --git a/network/netadaptercx/netvadapter/km/netvadapter.inf b/network/netadaptercx/netvadapter/km/netvadapter.inf Binary files differnew file mode 100644 index 00000000..a5565a86 --- /dev/null +++ b/network/netadaptercx/netvadapter/km/netvadapter.inf diff --git a/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj b/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj new file mode 100644 index 00000000..b9414ab8 --- /dev/null +++ b/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj @@ -0,0 +1,217 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B4044984-19DD-456F-9D47-565F59A47F5E}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>netvadapterkm</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <SupportsPackaging>true</SupportsPackaging> + </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> + <SkipPackageVerification>true</SkipPackageVerification> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapter</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapter</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemGroup> + <Inf Include="netvadapter.inf" /> + </ItemGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\driver.cpp" /> + <ClCompile Include="..\drivercode\device.cpp" /> + <ClCompile Include="..\drivercode\power.cpp" /> + <ClCompile Include="..\drivercode\memorymanagement.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\pch.hpp" /> + <ClInclude Include="..\drivercode\device.h" /> + <ClInclude Include="..\drivercode\power.h" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\netvadapterlibrary\ethernet_km\netvadapterlibrarykm.vcxproj"> + <Project>{e2a65efd-25cc-4af0-b180-0cd56ee277a9}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj.filters b/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj.filters new file mode 100644 index 00000000..3d80c128 --- /dev/null +++ b/network/netadaptercx/netvadapter/km/netvadapterkm.vcxproj.filters @@ -0,0 +1,51 @@ +<?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="netvadapter.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\power.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\memorymanagement.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\pch.hpp"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\device.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\power.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> diff --git a/network/netadaptercx/netvadapter/netvadapter.sln b/network/netadaptercx/netvadapter/netvadapter.sln new file mode 100644 index 00000000..e41c436d --- /dev/null +++ b/network/netadaptercx/netvadapter/netvadapter.sln @@ -0,0 +1,74 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11911.148 stable +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterkm", "km\netvadapterkm.vcxproj", "{B4044984-19DD-456F-9D47-565F59A47F5E}" + ProjectSection(ProjectDependencies) = postProject + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9} = {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterum", "um\netvadapterum.vcxproj", "{1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}" + ProjectSection(ProjectDependencies) = postProject + {612F33AD-430C-4FE7-8000-35E15A5EB757} = {612F33AD-430C-4FE7-8000-35E15A5EB757} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterlibrarykm", "..\netvadapterlibrary\ethernet_km\netvadapterlibrarykm.vcxproj", "{E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterlibraryum", "..\netvadapterlibrary\ethernet_um\netvadapterlibraryum.vcxproj", "{612F33AD-430C-4FE7-8000-35E15A5EB757}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|ARM64.Build.0 = Debug|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|x64.ActiveCfg = Debug|x64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|x64.Build.0 = Debug|x64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Debug|x64.Deploy.0 = Debug|x64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|ARM64.ActiveCfg = Release|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|ARM64.Build.0 = Release|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|ARM64.Deploy.0 = Release|ARM64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|x64.ActiveCfg = Release|x64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|x64.Build.0 = Release|x64 + {B4044984-19DD-456F-9D47-565F59A47F5E}.Release|x64.Deploy.0 = Release|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|ARM64.Build.0 = Debug|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|x64.ActiveCfg = Debug|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|x64.Build.0 = Debug|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Debug|x64.Deploy.0 = Debug|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|ARM64.ActiveCfg = Release|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|ARM64.Build.0 = Release|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|ARM64.Deploy.0 = Release|ARM64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|x64.ActiveCfg = Release|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|x64.Build.0 = Release|x64 + {1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}.Release|x64.Deploy.0 = Release|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|ARM64.Build.0 = Debug|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|x64.ActiveCfg = Debug|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|x64.Build.0 = Debug|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|ARM64.ActiveCfg = Release|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|ARM64.Build.0 = Release|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|x64.ActiveCfg = Release|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|x64.Build.0 = Release|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|ARM64.Build.0 = Debug|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|x64.ActiveCfg = Debug|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|x64.Build.0 = Debug|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|ARM64.ActiveCfg = Release|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|ARM64.Build.0 = Release|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|x64.ActiveCfg = Release|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B869660E-4622-49A7-A458-819E1C98599D} + EndGlobalSection +EndGlobal diff --git a/network/netadaptercx/netvadapter/um/netvadapterum.inf b/network/netadaptercx/netvadapter/um/netvadapterum.inf Binary files differnew file mode 100644 index 00000000..4b55d229 --- /dev/null +++ b/network/netadaptercx/netvadapter/um/netvadapterum.inf diff --git a/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj b/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj new file mode 100644 index 00000000..84579613 --- /dev/null +++ b/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <Inf Include="netvadapterum.inf" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{1CDC2CE3-19F3-4200-87C7-C343FB2D8ED3}</ProjectGuid> + <TemplateGuid>{2177f19c-eb4c-4687-9e7f-f9eec1f12cf1}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>netvadapterum</RootNamespace> + </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|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|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>33</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>33</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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>33</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>33</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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>33</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>33</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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>33</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>33</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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 /> + <PropertyGroup> + <SkipPackageVerification>true</SkipPackageVerification> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapterum</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapterum</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapterum</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + <TargetName>netvadapterum</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\netvadapterlibrary\Interface;..\..\netvadapterlibrary\code;..\..\..\..\wil\include;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\..\netvadapterlibrary\code\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\pch.hpp" /> + <ClInclude Include="..\drivercode\device.h" /> + <ClInclude Include="..\drivercode\power.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\driver.cpp" /> + <ClCompile Include="..\drivercode\device.cpp" /> + <ClCompile Include="..\drivercode\power.cpp" /> + <ClCompile Include="..\drivercode\memorymanagement.cpp" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\netvadapterlibrary\ethernet_um\netvadapterlibraryum.vcxproj"> + <Project>{612f33ad-430c-4fe7-8000-35e15a5eb757}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj.filters b/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj.filters new file mode 100644 index 00000000..b43c1b22 --- /dev/null +++ b/network/netadaptercx/netvadapter/um/netvadapterum.vcxproj.filters @@ -0,0 +1,51 @@ +<?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="netvadapterum.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\power.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\memorymanagement.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\pch.hpp"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\device.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\power.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> diff --git a/network/netadaptercx/netvadapterlibrary/Interface/netvadapter.h b/network/netadaptercx/netvadapterlibrary/Interface/netvadapter.h new file mode 100644 index 00000000..3ed87429 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/Interface/netvadapter.h @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +#define MAX_MULTICAST_LIST_SIZE 32 +#define MAC_ADDR_LEN 6 +#define MAX_RX_QUEUES 1 +#define MAX_TX_QUEUES 1 +#define MTU_SIZE 1500 + +#define NETV_NUMBER_OF_QUEUES 1 + +//#define NETV_SUPPORT_RSS // RSS not supported due to ENL limitations +//#define NETV_SUPPORT_TX_DEMUXING // TX Demuxing not supported due to ENL limitations + +// supported filters +#define NETV_SUPPORTED_FILTERS ( \ + NetPacketFilterFlagDirected | \ + NetPacketFilterFlagMulticast | \ + NetPacketFilterFlagBroadcast | \ + NetPacketFilterFlagPromiscuous | \ + NetPacketFilterFlagAllMulticast) + + +EVT_NET_ADAPTER_CREATE_TXQUEUE + CreateTxQueue; +EVT_NET_ADAPTER_CREATE_RXQUEUE + CreateRxQueue; + +typedef enum _NETV_FLOW_CONTROL +{ + NetvFlowControlDisabled = 0, + NetvFlowControlTxEnabled = 1, + NetvFlowControlRxEnabled = 2, + NetvFlowControlTxRxEnabled = 3, +} NETV_FLOW_CONTROL; + +typedef NTSTATUS(EVT_PDO_WAKE_SIGNAL)(_In_ void* Context); + +class NetvAdapter +{ + +public: + + NetvAdapter( + NETADAPTER Handle, + WDFDEVICE Device + ) noexcept; + + // Public API + void Destroy(); + NTSTATUS Initialize(); + NTSTATUS CreateRxQueue(_Inout_ NETRXQUEUE_INIT* NetRxQueueInit); + NTSTATUS CreateTxQueue(_Inout_ NETTXQUEUE_INIT* NetTxQueueInit); + + // Former INetvAdapter method (kept as regular method) + NTSTATUS ConfigureDataCapabilities(); + + // Existing public API + void SetPdoWakeSignalCallback(_In_ EVT_PDO_WAKE_SIGNAL* evtPdoWakeSignal, _In_ void* context); + void ArmWakeFromS0(void); + void DisarmWakeFromS0(void); + + NETADAPTER m_handle = WDF_NO_HANDLE; + + WDFDEVICE m_device = WDF_NO_HANDLE; + + // configuration + NET_ADAPTER_LINK_LAYER_ADDRESS PermanentAddress; + NET_ADAPTER_LINK_LAYER_ADDRESS CurrentAddress; + ULONG MACLastByte; + BOOLEAN S0Idle; + BOOLEAN EnableUsoUro; + + // Packet Filter and look ahead size. + NET_PACKET_FILTER_FLAGS PacketFilter; + + bool LinkAutoNeg{false}; + NETV_FLOW_CONTROL FlowControl; + + ULONG MtuSize; + ULONG CurrentPacketFilter; + ULONG NumMulticastAddresses; + NET_ADAPTER_LINK_LAYER_ADDRESS MulticastAddressList[MAX_MULTICAST_LIST_SIZE]; + + //ENL + LIST_ENTRY AdapterListLink; + ULONG LinkCount{1}; + ULONG LinkProcIndex; + ULONG EnlIndex; + ULONG EnlPortIndex; + BOOLEAN EnlIndexValid; + BOOLEAN EnlPortCreated; + BOOLEAN LinkPoll; + ULONG64 EnlTxDrops; + + // Offloads + bool UsoEnabled; + bool UroEnabled; + +private: + + _IRQL_requires_(PASSIVE_LEVEL) + void + SetLinkState( + void + ) const; + + + NTSTATUS NetvAdapterReadAddress(); +}; + +extern NetvAdapter* NetvAdapterGetContextFromWDFObject(NETADAPTER netAdapter); + +typedef struct _GLOBAL_CONTEXT +{ +} GLOBAL_CONTEXT; + +extern GLOBAL_CONTEXT NetvGlobalContext;
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/code/adapter.cpp b/network/netadaptercx/netvadapterlibrary/code/adapter.cpp new file mode 100644 index 00000000..880f970d --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/adapter.cpp @@ -0,0 +1,595 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <new.h> +#ifdef _KERNEL_MODE +#include <xfilter.h> +#else +#include "net/umxfilter.h" // Copied from Km XFilter.h, NETCX please move this xfilter.h into shared location +#endif +#include "netvadapter.h" +#include "rxqueue.h" +#include "txqueue.h" +#include "configuration.h" +#include "trace.h" +#include "memory.h" + +#include "adapter.tmh" + +UCHAR NetvMacAddressBase[MAC_ADDR_LEN] = { 0x22, 0x22, 0x22, 0x22, 0x00, 0x00 }; +const ULONG GSO_MAX_OFFLOAD_SIZE = 0xffff; +const ULONG GSO_MIN_SEGMENT_COUNT = 2; + +/* + * increasing beyond 1Gbps results in intermittent failure of + * netvadapter start due to buffer allocation failures in + * netadaptercx when running in nebula. + * tracked as bug 50671552 (if it doesn't get archived) + */ +static auto constexpr MAX_LINK_SPEED{1'000'000'000ull}; + +void +NetvEnlInterruptRoutine( + _Inout_ PVOID PortContext, + _In_ bool Tx +) +{ + NETPACKETQUEUE queue = (NETPACKETQUEUE)PortContext; + + if (Tx) // Tx + { + NetTxQueueNotifyMoreCompletedPacketsAvailable(queue); + } + else // Rx + { + NetRxQueueNotifyMoreReceivedPacketsAvailable(queue); + } +} + +static +EVT_PACKET_QUEUE_START + EvtTxQueueStart; + +static +EVT_PACKET_QUEUE_STOP + EvtTxQueueStop; + +static +EVT_PACKET_QUEUE_ADVANCE + EvtTxQueueAdvance; + +static +EVT_PACKET_QUEUE_CANCEL + EvtTxQueueCancel; + +static +EVT_PACKET_QUEUE_SET_NOTIFICATION_ENABLED + EvtTxQueueSetNotify; + +static +EVT_PACKET_QUEUE_START + EvtRxQueueStart; + +static +EVT_PACKET_QUEUE_STOP + EvtRxQueueStop; + +static +EVT_PACKET_QUEUE_ADVANCE + EvtRxQueueAdvance; + +static +EVT_PACKET_QUEUE_CANCEL + EvtRxQueueCancel; + +static +EVT_PACKET_QUEUE_SET_NOTIFICATION_ENABLED + EvtRxQueueSetNotify; + +NetvAdapter::NetvAdapter( + NETADAPTER Handle, + WDFDEVICE Device +) noexcept + : m_handle(Handle) + , m_device(Device) +{ +} + +NTSTATUS +NetvAdapter::Initialize( + void +) +{ + RETURN_IF_NOT_STATUS_SUCCESS( + NetvAdapterReadConfiguration(this, m_device)); + + RETURN_IF_NOT_STATUS_SUCCESS(NetvAdapterReadAddress()); + + SetLinkState(); + + NTSTATUS status = STATUS_SUCCESS; + + // Create ENL + EnlPortCreated = FALSE; + + if (NetvEnlMLink[EnlIndex].LinkCount == 0) + { + RETURN_IF_NOT_STATUS_SUCCESS( + EnlMCreateLink( + LinkCount, + LinkProcIndex, + LinkPoll, + &NetvEnlMLink[EnlIndex])); + } + + RETURN_NTSTATUS_IF(STATUS_INVALID_ADDRESS, + EnlMIsPortActive(&NetvEnlMLink[EnlIndex], EnlPortIndex)); + + status = EnlMActivateLinkPort( + &NetvEnlMLink[EnlIndex], + EnlPortIndex, + NetvEnlInterruptRoutine, + this); + + // what is the virtue of doing this? + if (NT_SUCCESS(status)) + { + EnlPortCreated = TRUE; + } + + RETURN_STATUS_SUCCESS(); +} + +void +NetvAdapter::Destroy( + void +) +{ + if (EnlPortCreated) + { + EnlMDeactivateLinkPort(&NetvEnlMLink[EnlIndex], EnlPortIndex); + EnlPortCreated = FALSE; + } + + if (EnlIndexValid && !EnlIsLinkActive(NetvEnlMLink[EnlIndex].LinkHandle[0])) + { + EnlMCloseLink(&NetvEnlMLink[EnlIndex]); + } +} + +_Use_decl_annotations_ +NTSTATUS +NetvAdapter::CreateRxQueue( + NETRXQUEUE_INIT * NetRxQueueInit + ) +{ + WDF_OBJECT_ATTRIBUTES rxAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&rxAttributes, NetvRxQueue); + rxAttributes.EvtDestroyCallback = [](WDFOBJECT Handle) { + NetvRxQueueGetContext(static_cast<NETPACKETQUEUE>(Handle))->Destroy(); + }; + + NET_PACKET_QUEUE_CONFIG rxConfig; + NET_PACKET_QUEUE_CONFIG_INIT( + &rxConfig, + EvtRxQueueAdvance, + EvtRxQueueSetNotify, + EvtRxQueueCancel); + rxConfig.EvtStart = EvtRxQueueStart; + rxConfig.EvtStop = EvtRxQueueStop; + + NETPACKETQUEUE rxQueue; + RETURN_IF_NOT_STATUS_SUCCESS(NetRxQueueCreate( + NetRxQueueInit, + &rxAttributes, + &rxConfig, + &rxQueue)); + + new (NetvRxQueueGetContext(rxQueue)) NetvRxQueue(rxQueue, *this); + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +NTSTATUS +NetvAdapter::CreateTxQueue( + NETTXQUEUE_INIT * NetTxQueueInit + ) +{ + WDF_OBJECT_ATTRIBUTES txAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&txAttributes, NetvTxQueue); + txAttributes.EvtDestroyCallback = [](WDFOBJECT Handle) { + NetvTxQueueGetContext(static_cast<NETPACKETQUEUE>(Handle))->Destroy(); + }; + + NET_PACKET_QUEUE_CONFIG txConfig; + NET_PACKET_QUEUE_CONFIG_INIT( + &txConfig, + EvtTxQueueAdvance, + EvtTxQueueSetNotify, + EvtTxQueueCancel); + txConfig.EvtStart = EvtTxQueueStart; + txConfig.EvtStop = EvtTxQueueStop; + + NETPACKETQUEUE txQueue; + RETURN_IF_NOT_STATUS_SUCCESS(NetTxQueueCreate( + NetTxQueueInit, + &txAttributes, + &txConfig, + &txQueue)); + + new (NetvTxQueueGetContext(txQueue)) NetvTxQueue(txQueue, *this); + + RETURN_STATUS_SUCCESS(); +} + +void NetvAdapter::SetPdoWakeSignalCallback(_In_ EVT_PDO_WAKE_SIGNAL* evtPdoWakeSignal, _In_ void* context) +{ + EnlSetPdoWakeSignalCallback(NetvEnlMLink[EnlIndex].LinkHandle[0], evtPdoWakeSignal, context); +} + +_Use_decl_annotations_ +_IRQL_requires_max_(PASSIVE_LEVEL) +void NetvAdapter::ArmWakeFromS0(void) +{ + if (EnlPortCreated) + { + ENLP_LINK* enLinkHandle = NetvEnlMLink[EnlIndex].LinkHandle[0]; + EnlArmWake(enLinkHandle); + } +} + +_Use_decl_annotations_ +_IRQL_requires_max_(PASSIVE_LEVEL) +void NetvAdapter::DisarmWakeFromS0(void) +{ + if (EnlPortCreated) + { + ENLP_LINK* enLinkHandle = NetvEnlMLink[EnlIndex].LinkHandle[0]; + EnlDisarmWake(enLinkHandle); + } +} + +_Use_decl_annotations_ +void +NetvAdapter::SetLinkState( + void +) const +{ + NET_ADAPTER_AUTO_NEGOTIATION_FLAGS autoNegotiationFlags{NetAdapterAutoNegotiationFlagNone}; + if (LinkAutoNeg) + { + autoNegotiationFlags |= + NetAdapterAutoNegotiationFlagXmitLinkSpeedAutoNegotiated | + NetAdapterAutoNegotiationFlagRcvLinkSpeedautoNegotiated | + NetAdapterAutoNegotiationFlagDuplexAutoNegotiated; + } + if (FlowControl != NetvFlowControlDisabled) + { + autoNegotiationFlags |= + NetAdapterAutoNegotiationFlagPauseFunctionsAutoNegotiated; + } + + NET_ADAPTER_PAUSE_FUNCTION_TYPE pauseFunctions{NetAdapterPauseFunctionTypeUnknown}; + switch (FlowControl) + { + case NetvFlowControlDisabled: + pauseFunctions = NetAdapterPauseFunctionTypeUnsupported; + break; + case NetvFlowControlRxEnabled: + pauseFunctions = NetAdapterPauseFunctionTypeReceiveOnly; + break; + case NetvFlowControlTxEnabled: + pauseFunctions = NetAdapterPauseFunctionTypeSendOnly; + break; + case NetvFlowControlTxRxEnabled: + pauseFunctions = NetAdapterPauseFunctionTypeSendAndReceive; + break; + } + + NET_ADAPTER_LINK_STATE linkState; + NET_ADAPTER_LINK_STATE_INIT( + &linkState, + MAX_LINK_SPEED, + MediaConnectStateConnected, + MediaDuplexStateFull, + pauseFunctions, + autoNegotiationFlags); + NetAdapterSetLinkState(m_handle, &linkState); +} + +static +void +EvtSetReceiveFilter( + _In_ NETADAPTER NetAdapter, + _In_ NETRECEIVEFILTER Handle + ) +{ + NetvAdapter* adapter = NetvAdapterGetContextFromWDFObject(NetAdapter); + + adapter->PacketFilter = NetReceiveFilterGetPacketFilter(Handle); + + adapter->NumMulticastAddresses = (ULONG)NetReceiveFilterGetMulticastAddressCount(Handle); + + RtlZeroMemory(adapter->MulticastAddressList, + sizeof(NET_ADAPTER_LINK_LAYER_ADDRESS) * MAX_MULTICAST_LIST_SIZE); + + if (adapter->NumMulticastAddresses != 0U) + { + NET_ADAPTER_LINK_LAYER_ADDRESS const * MulticastAddressList = NetReceiveFilterGetMulticastAddressList(Handle); + RtlCopyMemory(adapter->MulticastAddressList, + MulticastAddressList, + sizeof(NET_ADAPTER_LINK_LAYER_ADDRESS) * adapter->NumMulticastAddresses); + } +} + +static +_IRQL_requires_same_ +_IRQL_requires_max_(PASSIVE_LEVEL) +void +NTAPI +EvtNetAdapterOffloadSetRxXSum( + _In_ NETADAPTER Adapter, + _In_ NETOFFLOAD Offload + ) +{ + UNREFERENCED_PARAMETER((Adapter, Offload)); + ASSERT(NetOffloadIsRxChecksumIPv4Enabled(Offload)); + ASSERT(NetOffloadIsRxChecksumUdpEnabled(Offload)); +} + +static +_IRQL_requires_same_ +_IRQL_requires_max_(PASSIVE_LEVEL) +void +NTAPI +EvtNetAdapterOffloadSetGso( + _In_ NETADAPTER Adapter, + _In_ NETOFFLOAD Offload + ) +{ + auto adapter = NetvAdapterGetContextFromWDFObject(Adapter); + if (adapter->UsoEnabled) + { + // + // Since netvadapter only converts USO sends into URO receives, + // both must be enabled together, or disabled together. + // The order of callbacks is nondeterministic, so this can't assert + // that URO is enabled, since it might not have been enabled yet. + // This assert is so anyone using netvadapter knows that USO has + // been disabled after being enabled. + // + NT_FRE_ASSERTMSG("USO can't be disabled after being enabled", NetOffloadIsUsoIPv4Enabled(Offload)); + NT_FRE_ASSERTMSG("USO can't be disabled after being enabled", NetOffloadIsUsoIPv6Enabled(Offload)); + } + else + { + adapter->UsoEnabled = NetOffloadIsUsoIPv4Enabled(Offload) && NetOffloadIsUsoIPv6Enabled(Offload); + } +} + +static +_IRQL_requires_same_ +_IRQL_requires_max_(PASSIVE_LEVEL) +void +NTAPI +EvtNetAdapterOffloadSetRsc( + _In_ NETADAPTER Adapter, + _In_ NETOFFLOAD Offload + ) +{ + auto adapter = NetvAdapterGetContextFromWDFObject(Adapter); + if (adapter->UroEnabled) + { + // + // Since netvadapter only converts USO sends into URO receives, + // both must be enabled together, or disabled together. + // The order of callbacks is nondeterministic, so this can't assert + // that USO is enabled, since it might not have been enabled yet. + // This assert is so anyone using netvadapter knows that URO has + // been disabled after being enabled. + // This assert is important because if URO is disabled, netvadapter + // will forward the USO send without fixing it up or segmenting it, + // and the stack may behave badly. + // + NT_FRE_ASSERTMSG("URO can't be disabled after being enabled", NetOffloadIsUdpRscEnabled(Offload)); + } + else + { + adapter->UroEnabled = NetOffloadIsUdpRscEnabled(Offload); + } +} + +static +void +NetvAdapterSetUsoUroOffloadCapabilities( + _In_ NETADAPTER Adapter + ) +{ + NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES gsoCapabilities; + NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES_INIT( + &gsoCapabilities, + NetAdapterOffloadLayer3FlagIPv4NoOptions | NetAdapterOffloadLayer3FlagIPv6NoExtensions, + NetAdapterOffloadLayer4FlagUdp, + GSO_MAX_OFFLOAD_SIZE, + GSO_MIN_SEGMENT_COUNT, + EvtNetAdapterOffloadSetGso); + + NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES rscCapabilities; + NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES_INIT( + &rscCapabilities, + NetAdapterOffloadLayer3FlagIPv4NoOptions | NetAdapterOffloadLayer3FlagIPv6NoExtensions, + NetAdapterOffloadLayer4FlagUdp, + EvtNetAdapterOffloadSetRsc); + rscCapabilities.TcpTimestampOption = FALSE; + + NetAdapterOffloadSetGsoCapabilities(Adapter, &gsoCapabilities); + NetAdapterOffloadSetRscCapabilities(Adapter, &rscCapabilities); +} + +_Use_decl_annotations_ +NTSTATUS NetvAdapter::ConfigureDataCapabilities() +{ + + + NET_ADAPTER_TX_CAPABILITIES txCapabilities; + NET_ADAPTER_TX_CAPABILITIES_INIT(&txCapabilities, MAX_TX_QUEUES); + + NET_ADAPTER_RX_CAPABILITIES rxCapabilities; + NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED(&rxCapabilities, MAX_RX_BUFFER_SIZE, MAX_RX_QUEUES); + + NET_ADAPTER_LINK_LAYER_CAPABILITIES linkLayerCapabilities; + NET_ADAPTER_LINK_LAYER_CAPABILITIES_INIT(&linkLayerCapabilities, MAX_LINK_SPEED, MAX_LINK_SPEED); + + NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES receiveFilterCapabilities; + NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES_INIT(&receiveFilterCapabilities, EvtSetReceiveFilter); + receiveFilterCapabilities.SupportedPacketFilters = NETV_SUPPORTED_FILTERS; + receiveFilterCapabilities.MaximumMulticastAddresses = MAX_MULTICAST_LIST_SIZE; + + NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES xsumCapabilities; + NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT(&xsumCapabilities, EvtNetAdapterOffloadSetRxXSum); + + NetAdapterSetLinkLayerCapabilities(m_handle, &linkLayerCapabilities); + NetAdapterSetLinkLayerMtuSize(m_handle, MTU_SIZE); + NetAdapterSetDataPathCapabilities(m_handle, &txCapabilities, &rxCapabilities); + NetAdapterSetReceiveFilterCapabilities(m_handle, &receiveFilterCapabilities); + NetAdapterOffloadSetRxChecksumCapabilities(m_handle, &xsumCapabilities); + + NET_ADAPTER_LINK_LAYER_ADDRESS netvLinkAddress; + NET_ADAPTER_LINK_LAYER_ADDRESS_INIT(&netvLinkAddress, MAC_ADDR_LEN, (CONST UCHAR*)&(PermanentAddress.Address)); + + NetAdapterSetPermanentLinkLayerAddress(m_handle, &netvLinkAddress); + NetAdapterSetCurrentLinkLayerAddress(m_handle, &netvLinkAddress); + + if (EnableUsoUro) + { + NetvAdapterSetUsoUroOffloadCapabilities(m_handle); + } + + RETURN_STATUS_SUCCESS(); +} + +NTSTATUS +NetvAdapter::NetvAdapterReadAddress() +{ + PermanentAddress.Length = MAC_ADDR_LEN; + + RETURN_NTSTATUS_IF(STATUS_INVALID_ADDRESS, + MACLastByte < 1 || + MACLastByte > MAX_ADAPTER_COUNT); + + ETH_COPY_NETWORK_ADDRESS(PermanentAddress.Address, NetvMacAddressBase); + PermanentAddress.Address[MAC_ADDR_LEN - 1] = (UCHAR) MACLastByte; + + if (ETH_IS_MULTICAST(PermanentAddress.Address) || + ETH_IS_BROADCAST(PermanentAddress.Address)) + { + RETURN_IF_NOT_STATUS_SUCCESS(STATUS_INVALID_ADDRESS); + } + + RtlCopyMemory( + &CurrentAddress, + &PermanentAddress, + sizeof(PermanentAddress) + ); + + EnlIndex = (MACLastByte - 1) >> 1; + EnlPortIndex = (MACLastByte - 1) & 1; + EnlIndexValid = TRUE; + + RETURN_STATUS_SUCCESS(); +} + +_Use_decl_annotations_ +void +EvtTxQueueStart( + NETPACKETQUEUE Queue +) +{ + NetvTxQueueGetContext(Queue)->Start(); +} + +_Use_decl_annotations_ +void +EvtTxQueueStop( + NETPACKETQUEUE Queue +) +{ + NetvTxQueueGetContext(Queue)->Stop(); +} + +_Use_decl_annotations_ +void +EvtTxQueueAdvance( + NETPACKETQUEUE Queue +) +{ + NetvTxQueueGetContext(Queue)->Advance(); +} + +_Use_decl_annotations_ +void +EvtTxQueueCancel( + NETPACKETQUEUE Queue +) +{ + NetvTxQueueGetContext(Queue)->Cancel(); +} + +_Use_decl_annotations_ +void +EvtTxQueueSetNotify( + NETPACKETQUEUE Queue, + BOOLEAN Enable +) +{ + NetvTxQueueGetContext(Queue)->SetNotify(Enable); +} + +_Use_decl_annotations_ +void +EvtRxQueueStart( + NETPACKETQUEUE Queue +) +{ + NetvRxQueueGetContext(Queue)->Start(); +} + +_Use_decl_annotations_ +void +EvtRxQueueStop( + NETPACKETQUEUE Queue +) +{ + NetvRxQueueGetContext(Queue)->Stop(); +} + + +_Use_decl_annotations_ +void +EvtRxQueueAdvance( + NETPACKETQUEUE Queue +) +{ + NetvRxQueueGetContext(Queue)->Advance(); +} + +_Use_decl_annotations_ +void +EvtRxQueueCancel( + NETPACKETQUEUE Queue +) +{ + NetvRxQueueGetContext(Queue)->Cancel(); +} + +_Use_decl_annotations_ +void +EvtRxQueueSetNotify( + NETPACKETQUEUE Queue, + BOOLEAN Enable +) +{ + NetvRxQueueGetContext(Queue)->SetNotify(Enable); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/configuration.cpp b/network/netadaptercx/netvadapterlibrary/code/configuration.cpp new file mode 100644 index 00000000..7482ef84 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/configuration.cpp @@ -0,0 +1,102 @@ +#include "pch.hpp" +#include "netvadapter.h" + +#include "trace.h" +#include "configuration.tmh" + +typedef struct _NETVADAPTER_ADVANCED_PROPERTY +{ + UNICODE_STRING RegName; // variable name text + UINT32 FieldOffset; // offset to NetvAdapter field + UINT32 FieldSize; // size (in bytes) of the field + UINT32 Default; // default value to use + UINT32 Min; // minimum value allowed + UINT32 Max; // maximum value allowed +} NETVADAPTER_ADVANCED_PROPERTY; + +#define NETV_OFFSET(field) ((UINT32)FIELD_OFFSET(NetvAdapter,field)) +#define NETV_SIZE(field) RTL_FIELD_SIZE(NetvAdapter,field) + +#define CONSTANT_UNICODE_STRING(s) {sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s } + +NETVADAPTER_ADVANCED_PROPERTY NetvSupportedProperties[] = +{ + // reg value name - Offset in NetvAdapter - Field size - Default Value - Min - Max + + // Standard Keywords + { CONSTANT_UNICODE_STRING(L"MACLastByte"), NETV_OFFSET(MACLastByte), NETV_SIZE(MACLastByte), 0, 0, 254 }, + { CONSTANT_UNICODE_STRING(L"LinkProcIndex"), NETV_OFFSET(LinkProcIndex), NETV_SIZE(LinkProcIndex), 1000, 0, 1023 }, + { CONSTANT_UNICODE_STRING(L"S0Idle"), NETV_OFFSET(S0Idle), NETV_SIZE(S0Idle), 0, 0, 1 }, + { CONSTANT_UNICODE_STRING(L"EnableUsoUro"), NETV_OFFSET(EnableUsoUro), NETV_SIZE(EnableUsoUro), 0, 0, 1 }, +}; + +NTSTATUS +NetvAdapterReadConfiguration( + NetvAdapter *Adapter, + WDFDEVICE Device + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + NETCONFIGURATION configuration; + RETURN_IF_NOT_STATUS_SUCCESS( + NetDeviceOpenConfiguration(Device, WDF_NO_OBJECT_ATTRIBUTES, &configuration)); + + // read all the registry values + for (auto &property : NetvSupportedProperties) + { + // Driver should NOT fail the initialization only because it can not + // read the registry + auto pointer = (PUCHAR)Adapter + property.FieldOffset; + + // Get the configuration value for a specific parameter. Under NT the + // parameters are all read in as DWORDs. + ULONG value = 0; + + status = NetConfigurationQueryUlong( + configuration, + NET_CONFIGURATION_QUERY_ULONG_NO_FLAGS, + &property.RegName, + &value); + + // Store the value in the adapter structure. + switch (property.FieldSize) + { + case 1: + *((PUCHAR)pointer) = (UCHAR)value; + break; + + case 2: + *((PUSHORT)pointer) = (USHORT)value; + break; + + case 4: + *((PULONG)pointer) = (ULONG)value; + break; + + default: + break; + } + + // If the parameter was present, then check its value for validity. + if (NT_SUCCESS(status)) + { + // Check that param value is not too small or too large + + if (value < property.Min || + value > property.Max) + { + value = property.Default; + } + } + else + { + value = property.Default; + status = STATUS_SUCCESS; + } + } + + NetConfigurationClose(configuration); + + RETURN_STATUS_SUCCESS(); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/configuration.h b/network/netadaptercx/netvadapterlibrary/code/configuration.h new file mode 100644 index 00000000..0bfe0170 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/configuration.h @@ -0,0 +1,8 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +NTSTATUS +NetvAdapterReadConfiguration( + NetvAdapter *Adapter, + WDFDEVICE Device + ); + diff --git a/network/netadaptercx/netvadapterlibrary/code/enl.cpp b/network/netadaptercx/netvadapterlibrary/code/enl.cpp new file mode 100644 index 00000000..709c5a1e --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/enl.cpp @@ -0,0 +1,1001 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "pch.hpp" +#include <stdlib.h> +#include "netvadapter.h" +#include "rxqueue.h" +#include "txqueue.h" +#include "trace.h" +#include "memory.h" +#include "rtl\KLockHolder.h" +#include "enl.tmh" + +/////////////////////////////////////////////////////////////////////////////// +// BEGIN Generic execution engine thread lib // +/////////////////////////////////////////////////////////////////////////////// + +ENL_MLINK NetvEnlMLink[MAX_ADAPTER_COUNT / 2]; + +/*++ +The iteration routine performs one full pass over all input queues and +any internal queues (that might be holding previous items waiting to be +processed). +--*/ + +static +SIZE_T +CopyTxPacketDataToBuffer( + _Out_writes_bytes_(BufferLength) PUCHAR BufferDest, + _In_ NET_RING_PACKET_ITERATOR const * Iterator, + _In_ NET_EXTENSION const * VirtualAddressExtension, + _In_ SIZE_T BufferLength) +{ + SIZE_T bytesCopied = 0; + + for (NET_RING_FRAGMENT_ITERATOR fi = NetPacketIteratorGetFragments(Iterator); + NetFragmentIteratorHasAny(&fi) && (BufferLength > 0); + NetFragmentIteratorAdvance(&fi)) + { + NET_FRAGMENT const * fragment = NetFragmentIteratorGetFragment(&fi); + NET_FRAGMENT_VIRTUAL_ADDRESS const * virtualAddress = + NetExtensionGetFragmentVirtualAddress(VirtualAddressExtension, NetFragmentIteratorGetIndex(&fi)); + + UCHAR const * pPacketData = (UCHAR const *)virtualAddress->VirtualAddress + fragment->Offset; + SIZE_T bytesToCopy = + (BufferLength < (SIZE_T) fragment->ValidLength) ? BufferLength : (SIZE_T) fragment->ValidLength; + RtlCopyMemory(BufferDest, pPacketData, bytesToCopy); + + bytesCopied += bytesToCopy; + BufferDest += bytesToCopy; + BufferLength -= bytesToCopy; + } + + return bytesCopied; +} + +VOID +EnlpAffinitizeThread( + _In_ ULONG ProcIndex, + _In_ ULONG IdealNode + ) +{ + LogInformation(FLAG_DRIVER, L"ProcIndex=%u", ProcIndex); + NTSTATUS status; + PROCESSOR_NUMBER procNumber = { 0 }; + GROUP_AFFINITY affinity = { 0 }; + + if (ProcIndex == 999) + { + // No affinity at all + return; + } + + if (ProcIndex == 1000 || (ProcIndex >= 1001 && ProcIndex <= 1004)) + { + KeQueryNodeActiveAffinity((USHORT)IdealNode, &affinity, NULL); + + if (ProcIndex == 1000) + { + // Affinitize to all the procs in the Node + NOTHING; + } + else + { + // Affinitize to the highest numbered proc in the Node for 1001, + // next highest numbered proc for 1002, ... + ULONG index; +#ifdef _WIN64 + NT_FRE_ASSERTMSG("Failed to find bit", TRUE == BitScanReverse64(&index, (ULONG64)affinity.Mask)); + affinity.Mask = (KAFFINITY)((ULONG64)1 << (index - (ProcIndex - 1001))); +#else + NT_FRE_ASSERTMSG("Failed to find bit", TRUE == BitScanReverse(&index, (ULONG)affinity.Mask)); + affinity.Mask = (KAFFINITY)((ULONG)1 << (index - (ProcIndex - 1001))); +#endif + } + } + else + { + // Affinitize the specifically requested proc + status = KeGetProcessorNumberFromIndex(ProcIndex, &procNumber); + NT_FRE_ASSERTMSG("Bad ProcIndex", NT_SUCCESS(status)); + + affinity.Group = procNumber.Group; + affinity.Mask = AFFINITY_MASK(procNumber.Number); + } + + EnlThreadSetAffinity(&affinity, NULL); +} + +ENL_START_ROUTINE EnlpThreadRoutine; + +NTSTATUS +EnlpStartThread( + _In_ ULONG ProcIndex, + _In_ ULONG IdealNode, + _In_ ENLP_ITERATION_ROUTINE* IterationRoutine, + _In_ PVOID IterationContext, + _In_opt_ KAutoEvent* ArmWaitEvent, + _Out_ ENLP_THREAD_STATE* EnlThread + ) +{ + LogInformation(FLAG_DRIVER, L"ProcIndex=%u EnlThread=%p", ProcIndex, EnlThread); + + EnlThread->PauseRequested = TRUE; + EnlThread->StopRequested = FALSE; + EnlThread->IterationRoutine = IterationRoutine; + EnlThread->IterationContext = IterationContext; + EnlThread->ArmWaitEvent = ArmWaitEvent; + + EnlThread->ProcIndex = ProcIndex; + EnlThread->IdealNode = IdealNode; + + RETURN_IF_NOT_STATUS_SUCCESS( + EnlThreadCreate(EnlpThreadRoutine, EnlThread, EnlThread->Thread)); + + EnlThreadSetPriority(EnlThread->Thread, 15); + + RETURN_STATUS_SUCCESS(); +} + +BOOLEAN +EnlpIsThreadPaused( + _In_ CONST ENLP_THREAD_STATE* EnlThread + ) +{ + return EnlThread->PauseRequested; +} + +VOID +EnlpPauseThread( + _Inout_ ENLP_THREAD_STATE* EnlThread + ) +{ + LogInformation(FLAG_DRIVER, L"EnlThread=%p", EnlThread); + if (!EnlpIsThreadPaused(EnlThread)) + { + WriteBooleanNoFence(&EnlThread->PauseRequested, TRUE); + if (EnlThread->ArmWaitEvent != NULL) + { + EnlThread->ArmWaitEvent->Set(); + } + EnlThread->PausingEvent.Wait(); + } +} + +VOID +EnlpResumeThread( + _Inout_ ENLP_THREAD_STATE* EnlThread + ) +{ + LogInformation(FLAG_DRIVER, L"EnlThread=%p", EnlThread); + if (EnlpIsThreadPaused(EnlThread)) + { + WriteBooleanNoFence(&EnlThread->PauseRequested, FALSE); + KeMemoryBarrier(); + EnlThread->ResumeEvent.Set(); + } +} + +VOID +EnlpStopThread( + _Inout_ ENLP_THREAD_STATE* EnlThread + ) +{ + LogInformation(FLAG_DRIVER, L"EnlThread=%p", EnlThread); + if (EnlThread->Thread != NULL) + { + WriteBooleanNoFence(&EnlThread->StopRequested, TRUE); + EnlpResumeThread(EnlThread); // in case thread was paused + EnlThreadWaitForTermination(EnlThread->Thread); + EnlThread->Thread.reset(); + } +} + +ENL_THREAD_ROUTINE_RETURN +EnlpThreadRoutine( + _In_ PVOID Context + ) +{ + ENLP_THREAD_STATE* enlThread = (ENLP_THREAD_STATE*)Context; + + // + // Affinitize the thread + // + EnlpAffinitizeThread(enlThread->ProcIndex, enlThread->IdealNode); + + // + // ENL thread starts at paused state. + // + enlThread->ResumeEvent.Wait(); + + for (;;) + { + + if (ReadBooleanNoFence(&enlThread->PauseRequested)) + { + enlThread->PausingEvent.Set(); + enlThread->ResumeEvent.Wait(); + } + + if (ReadBooleanNoFence(&enlThread->StopRequested)) + { + break; + } + + enlThread->IterationRoutine(enlThread->IterationContext); + } + + return ENL_THREAD_ROUTINE_RETURN(); +} + +/////////////////////////////////////////////////////////////////////////////// +// END Generic execution engine thread lib // +/////////////////////////////////////////////////////////////////////////////// + +BOOLEAN +enlpCheckAndArmQueue( + _Inout_ ENLP_QUEUE* Q + ) +{ + BOOLEAN armed = FALSE; + auto ringBuffer = Q->Queue->GetPacketRing(); + // If Q is still empty, take the lock, and if still empty under lock, then + // arm it. + if (ringBuffer->BeginIndex == ringBuffer->EndIndex) + { + WdfSpinLockAcquire(Q->Spinlock); + + if (ringBuffer->BeginIndex == ringBuffer->EndIndex) + { + armed = TRUE; + Q->Armed = TRUE; + } + + WdfSpinLockRelease(Q->Spinlock); + } + + return armed; +} + +VOID +enlpArmAndWait( + _Inout_ ENLP_LINK* EnlLink + ) +{ + ULONG pi, ci; + + for (pi = 0; pi < ENLP_PORT_COUNT; pi++) + { + ENLP_PORT* port = &EnlLink->Ports[pi]; + + for (ci = 0; ci < port->TxQueueCount; ci++) + { + if (!enlpCheckAndArmQueue(port->TxQueue)) + { + return; + } + } + } + + EnlLink->ArmWaitEvent.Wait(); +} + +VOID +EnlpIterationRoutine( + _In_ PVOID IterationContext + ) +{ + auto enlLink = reinterpret_cast<ENLP_LINK *>(IterationContext); + bool emptyTx = true; + // + // Drain up to TX_BATCH_COUNT items from all tx queues first. + // + + for (size_t pi = 0U; pi < ENLP_PORT_COUNT; pi++) + { + auto txport = &enlLink->Ports[pi]; + auto rxport = &enlLink->Ports[pi ^ 0x1]; // 0 -> 1, 1 -> 0 + + for (size_t ci = 0U; ci < txport->TxQueueCount; ci++) + { + auto txq = &txport->TxQueue[ci]; + if (txq->State != Started) + continue; + + NET_RING_PACKET_ITERATOR txPi = { + txq->Queue->m_rings, nullptr, txq->QueueNext, txq->QueueEnd + }; + + while (NetPacketIteratorHasAny(&txPi)) + { + bool rxDrop = TRUE; + auto txPacket = NetPacketIteratorGetPacket(&txPi); + + emptyTx = FALSE; + + if (enlLink->ArmedForWake) + { + // Save wake packet and trigger a wake signal, any other frames queued after the wake + // packet will be dropped + enlLink->WakeFrameSize = CopyTxPacketDataToBuffer( + &enlLink->WakeFrame[0], + &txPi, + &txq->TxQueue->VirtualAddressExtension, + sizeof(enlLink->WakeFrame)); +#if _KERNEL_MODE + enlLink->EvtWakeSignal(enlLink->WakeSignalContext); +#endif + + // Make sure to disarm wake, otherwise this thread might overwrite the original wake frame + EnlDisarmWake(enlLink); + } + + if (rxport->RxQueueCount > 0) + { + //TODO: Currently does 1:1 mapping between Tx and Rx. Need to set up indirection table + auto rxq = &rxport->RxQueue[ci]; + + if (rxq->State == Started) + { + NET_RING_FRAGMENT_ITERATOR rxFi = { + rxq->Queue->m_rings, nullptr, rxq->QueueNext, rxq->QueueEnd + }; + + auto rxPi = NetRingGetPostPackets(rxq->Queue->m_rings); + + if (NetFragmentIteratorHasAny(&rxFi) && NetPacketIteratorHasAny(&rxPi)) + { + rxDrop = FALSE; + + auto fragment = NetFragmentIteratorGetFragment(&rxFi); + BYTE* fragmentBuffer = nullptr; + + auto const rxVirtualAddress = + NetExtensionGetFragmentVirtualAddress( + &rxq->RxQueue->VirtualAddressExtension, + NetFragmentIteratorGetIndex(&rxFi)); + + fragmentBuffer = static_cast<BYTE *>(rxVirtualAddress->VirtualAddress); + + fragment->Offset = 0; + fragment->ValidLength = + CopyTxPacketDataToBuffer( + fragmentBuffer, + &txPi, + &txq->TxQueue->VirtualAddressExtension, + static_cast<SIZE_T>(fragment->Capacity)); + + auto rxPacket = NetPacketIteratorGetPacket(&rxPi); + rxPacket->FragmentIndex = NetFragmentIteratorGetIndex(&rxFi); + rxPacket->FragmentCount = 1; + + if (enlLink->InitializePacketLayout) + { + rxPacket->Layout = txPacket->Layout; + } + else + { + rxPacket->Layout = {}; + } + + if (rxq->RxQueue->RxXSumExtension.Enabled) + { + auto RxXSum = NetExtensionGetPacketChecksum( + &rxq->RxQueue->RxXSumExtension, + NetPacketIteratorGetIndex(&rxPi)); + RxXSum->Layer2 = NetPacketRxChecksumEvaluationNotChecked; + RxXSum->Layer3 = NetPacketRxChecksumEvaluationValid; + RxXSum->Layer4 = NetPacketRxChecksumEvaluationValid; + } + + if (rxq->RxQueue->UdpRscExtension.Enabled && + txq->TxQueue->UsoExtension.Enabled) + { + auto txUso = NetExtensionGetPacketGso( + &txq->TxQueue->UsoExtension, + NetPacketIteratorGetIndex(&txPi)); + if (txPacket->Layout.Layer4Type == NetPacketLayer4TypeUdp && + txUso->UDP.Mss > 0) + { + if (txPacket->Layout.Layer3Type == NetPacketLayer3TypeIPv6NoExtensions) + { + UINT16* ipv6PayloadLength = (UINT16*)(fragmentBuffer + txPacket->Layout.Layer2HeaderLength + 4); + *ipv6PayloadLength = _byteswap_ushort( + (USHORT)(fragment->ValidLength - + (txPacket->Layout.Layer2HeaderLength + txPacket->Layout.Layer3HeaderLength))); + } + else if (txPacket->Layout.Layer3Type == NetPacketLayer3TypeIPv4NoOptions) + { + UINT16* ipv4TotalLength = (UINT16*)(fragmentBuffer + txPacket->Layout.Layer2HeaderLength + 2); + *ipv4TotalLength = _byteswap_ushort((USHORT)(fragment->ValidLength - txPacket->Layout.Layer2HeaderLength )); + NT_FRE_ASSERT(*ipv4TotalLength > 0); + } + + UINT16* udpPayloadLength = (UINT16*)(fragmentBuffer + txPacket->Layout.Layer2HeaderLength + + txPacket->Layout.Layer3HeaderLength + 4); + *udpPayloadLength = _byteswap_ushort( + (USHORT)(fragment->ValidLength - + (txPacket->Layout.Layer3HeaderLength + txPacket->Layout.Layer2HeaderLength))); + + // Set the checksum to zero + UINT16* udpChecksum = udpPayloadLength + 1; + *udpChecksum = 0; + + auto rxUro = NetExtensionGetPacketRsc( + &rxq->RxQueue->UdpRscExtension, + NetPacketIteratorGetIndex(&rxPi)); + rxUro->UDP.CoalescedSegmentSize = (UINT16)txUso->UDP.Mss; + rxUro->UDP.CoalescedSegmentCount = + (UINT16)((fragment->ValidLength - txPacket->Layout.Layer3HeaderLength - txPacket->Layout.Layer4HeaderLength + + txUso->UDP.Mss - 1) / txUso->UDP.Mss); + NT_FRE_ASSERT(rxUro->UDP.CoalescedSegmentCount > 1); + NT_FRE_ASSERT(*udpPayloadLength >= 8); + } + } + + // prevent any reordering the tx/rx completion flag + KeMemoryBarrier(); + + // Use Scratch field as completion flag for the rx fragment + fragment->Scratch = 1; + rxPacket->Scratch = 1; + + NetFragmentIteratorAdvance(&rxFi); + NetPacketIteratorAdvance(&rxPi); + + rxq->QueueNext = NetFragmentIteratorGetIndex(&rxFi); + NetPacketIteratorSet(&rxPi); + + if (rxq->Notify) + { + rxport->Interrupt(rxq->Queue->m_handle, rxq->TxRx); + } + } + } + } + + if (rxDrop) + { + // TODO - add rxdrop stat + } + + // Use Scratch field as completion flag for the tx packet + txPacket->Scratch = 1; + NetPacketIteratorAdvance(&txPi); + } + + if (!emptyTx) + { + if (txq->Notify) + { + txport->Interrupt(txq->Queue->m_handle, txq->TxRx); + } + + // Store the next index so that the EnlThread knows which packet to start from in the next iteration + txq->QueueNext = NetPacketIteratorGetIndex(&txPi); + } + } + } + + ULONG64 ts; + + if (emptyTx) + { + if (enlLink->Poll == FALSE) + { + enlpArmAndWait(enlLink); + } + + ts = ReadTimeStampCounter(); + enlLink->EmptyTicks += (ts - enlLink->Ts); + } + else + { + ts = ReadTimeStampCounter(); + enlLink->BusyTicks += (ts - enlLink->Ts); + } + + enlLink->Ts = ts; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +ENLP_QUEUE * +EnlCreateQueue( + _In_ NETPACKETQUEUE Queue, + _In_ BOOLEAN Tx + ) +{ + ENLP_LINK* enlLink; + ENLP_PORT* port; + ENLP_QUEUE* enlQueue; + NTSTATUS status; + + if (Tx) // Tx + { + NetvTxQueue* netvTxQueue = NetvTxQueueGetContext(Queue); + enlLink = NetvEnlMLink[netvTxQueue->m_adapter.EnlIndex].LinkHandle[0]; + port = &enlLink->Ports[netvTxQueue->m_adapter.EnlPortIndex]; + enlQueue = &port->TxQueue[0]; // Change to accommodate multiple Queues + enlQueue->Queue = netvTxQueue; + enlQueue->TxQueue = netvTxQueue; + enlQueue->State = Stopped; + enlQueue->ArmWaitEvent = &enlLink->ArmWaitEvent; + enlQueue->QueueNext = 0; + enlQueue->QueueEnd = 0; + enlQueue->TxRx = TX; + enlQueue->EnlPortHandle = port; + port->TxQueueCount++; + LogInformation(FLAG_DRIVER, L"Adapter=%p Queue=%Iu TxQueue=%p", + &netvTxQueue->m_adapter, reinterpret_cast<ULONG_PTR>(Queue), netvTxQueue); + } + else // Rx + { + NetvRxQueue* netvRxQueue = NetvRxQueueGetContext(Queue); + enlLink = NetvEnlMLink[netvRxQueue->m_adapter.EnlIndex].LinkHandle[0]; + port = &enlLink->Ports[netvRxQueue->m_adapter.EnlPortIndex]; + enlQueue = &port->RxQueue[0]; // Change to accommodate multiple Queues + enlQueue->Queue = netvRxQueue; + enlQueue->RxQueue = netvRxQueue; + enlQueue->State = Stopped; + enlQueue->QueueNext = 0; + enlQueue->QueueEnd = 0; + enlQueue->TxRx = RX; + enlQueue->EnlPortHandle = port; + port->RxQueueCount++; + LogInformation(FLAG_DRIVER, L"Adapter=%p Queue=%Iu RxQueue=%p", + &netvRxQueue->m_adapter, reinterpret_cast<ULONG_PTR>(Queue), netvRxQueue); + } + + // Create WDF spinlock for the queue, parent to the queue's WDF handle + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = enlQueue->Queue->m_handle; + status = WdfSpinLockCreate(&attributes, &enlQueue->Spinlock); + NT_ASSERT(NT_SUCCESS(status)); + + + EnlpResumeThread(&enlLink->EnlThread); + + return enlQueue; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlDestroyQueue( + _In_ ENLP_QUEUE * Queue, + _In_ BOOLEAN Tx + ) +{ + LogInformation(FLAG_DRIVER, L"Queue=%p", Queue); + ENLP_PORT* port = Queue->EnlPortHandle; + + if (Tx) + { + port->TxQueueCount--; + } + else + { + port->RxQueueCount--; + } + + Queue->ArmWaitEvent = nullptr; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlRingDoorBell( + _In_ ENLP_QUEUE * Queue, + _In_ ULONG EndIndex + ) +{ + InterlockedExchange((volatile LONG *)&Queue->QueueEnd, (LONG)EndIndex); + + WdfSpinLockAcquire(Queue->Spinlock); + + if (Queue->Armed) + { + NT_ASSERT(Queue->ArmWaitEvent != NULL); + Queue->Armed = FALSE; + WdfSpinLockRelease(Queue->Spinlock); + Queue->ArmWaitEvent->Set(); + return; + } + + WdfSpinLockRelease(Queue->Spinlock); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlArmInterrupt( + _In_ ENLP_QUEUE * Queue, + _In_ BOOLEAN notificationEnabled + ) +{ + Queue->Notify = notificationEnabled; + + // TODO: InterlockedExchange reduces the throughput of the ENL from about 500MB/s to 8MB/s. -> why + //InterlockedExchange((volatile LONG *)&Queue->Notify, (LONG)notificationEnabled); +} + +_Use_decl_annotations_ +VOID +EnlIndicateQueueState( + ENLP_QUEUE * Queue, + ENL_QUEUE_STATE State + ) +{ + Queue->State = State; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlCreateLink( + _In_ ULONG ProcessorIndex, + _In_ ULONG IdealNode, + _In_ BOOLEAN Poll, + _In_ BOOLEAN InitializePacketLayout, + _Out_ ENLP_LINK ** EnlLink + ) +{ + LogInformation(FLAG_DRIVER, L"ProcessorIndex=%u", ProcessorIndex); + + auto enlLink = wil::make_unique_nothrow<ENLP_LINK>(); + RETURN_NTSTATUS_IF( + STATUS_INSUFFICIENT_RESOURCES, + ! enlLink); + + enlLink->Ts = ReadTimeStampCounter(); + enlLink->Poll = Poll; + enlLink->InitializePacketLayout = InitializePacketLayout; + + RETURN_IF_NOT_STATUS_SUCCESS( + EnlpStartThread( + ProcessorIndex, + IdealNode, + EnlpIterationRoutine, + enlLink.get(), + enlLink->Poll ? NULL : &enlLink->ArmWaitEvent, + &enlLink->EnlThread)); + + *EnlLink = enlLink.release(); + + RETURN_STATUS_SUCCESS(); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlIsPortActive( + _In_ ENLP_LINK * EnlLink, + _In_ ULONG PortIndex + ) +{ + ENLP_PORT* port = &EnlLink->Ports[PortIndex]; + ENLP_QUEUE* txq = &port->TxQueue[0]; + NT_FRE_ASSERT(PortIndex < ENLP_PORT_COUNT); + + return (txq->Queue == nullptr) ? FALSE : TRUE; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlIsLinkActive( + _In_ ENLP_LINK * EnlLink + ) +{ + return (EnlIsPortActive(EnlLink, 0) || EnlIsPortActive(EnlLink, 1)); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlActivateLinkPort( + _In_ ENLP_LINK * EnlLink, + _In_ ULONG PortIndex, + _In_ ENL_INTERRUPT_ROUTINE Interrupt, + _In_ PVOID PortContext + ) +{ + ENLP_PORT* port = &EnlLink->Ports[PortIndex]; + + LogInformation(FLAG_DRIVER, L"PortIndex=%u Queue=%p", PortIndex, port->TxQueue[0].Queue); + + NT_FRE_ASSERT(!EnlIsPortActive(EnlLink, PortIndex)); + NT_FRE_ASSERT(port->TxQueueCount == 0); + NT_FRE_ASSERT(port->RxQueueCount == 0); + + port->Interrupt = Interrupt; + port->PortContext = PortContext; + + RETURN_STATUS_SUCCESS(); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlDeactivateLinkPort( + _In_ ENLP_LINK * EnlLink, + _In_ ULONG PortIndex + ) +{ + NT_FRE_ASSERT(PortIndex < ENLP_PORT_COUNT); + + ENLP_PORT* port = &EnlLink->Ports[PortIndex]; + LogInformation(FLAG_DRIVER, L"PortIndex=%u Queue=%p", PortIndex, port->TxQueue[0].Queue); + + NT_FRE_ASSERT(EnlIsPortActive(EnlLink, PortIndex)); + + KLockThisExclusive(EnlLink->Lock); + NT_FRE_ASSERT(!EnlpIsThreadPaused(&EnlLink->EnlThread)); + EnlpPauseThread(&EnlLink->EnlThread); + +#if _KERNEL_MODE + KeFlushQueuedDpcs(); +#endif + + port->PortContext = NULL; + + //Clears reference to only first queue - Change for all queues + port->TxQueue[0].Queue = nullptr; + port->RxQueue[0].Queue = nullptr; + + + // As long as there's one port with active queues, the EnlThread will run. + for (ULONG i = 0; i < ENLP_PORT_COUNT; i++) + { + if (EnlIsPortActive(EnlLink, i)) + { + EnlpResumeThread(&EnlLink->EnlThread); + break; + } + } +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlCloseLink( + _In_ ENLP_LINK * EnlLink + ) +{ + ULONG i; + + for (i = 0; i < ENLP_PORT_COUNT; i++) + { + NT_FRE_ASSERT(!EnlIsPortActive(EnlLink, i)); + } + + EnlpStopThread(&EnlLink->EnlThread); + + delete EnlLink; +} + +/////////////////////////////////////////////////////////////////////////////// +// Multi link wrapper APIs // +/////////////////////////////////////////////////////////////////////////////// + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlMCreateLink( + _In_range_(1, ENL_MLINK_MAX)ULONG LinkCount, + _In_reads_(LinkCount) ULONG ProcessorIndex, + _In_ BOOLEAN Poll, + _Out_ ENL_MLINK* EnlMLink + ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG i = 0; + + RtlZeroMemory(EnlMLink, sizeof(*EnlMLink)); + + if (LinkCount < 1 || LinkCount > ENL_MLINK_MAX || + (LinkCount & (LinkCount - 1)) != 0) + { + status = STATUS_REQUEST_NOT_ACCEPTED; + goto exit; + } + + for (i = 0; i < LinkCount; i++) + { +#ifdef _KERNEL_MODE + const BOOLEAN initializePacketLayout = TRUE; +#else + const BOOLEAN initializePacketLayout = FALSE; +#endif + status = EnlCreateLink(ProcessorIndex, 0, Poll, initializePacketLayout, &EnlMLink->LinkHandle[i]); + + if (!NT_SUCCESS(status)) + { + goto exit; + } + } + + EnlMLink->LinkCount = LinkCount; + +exit: + + if (!NT_SUCCESS(status)) + { + for (; i > 0; i--) + { + EnlCloseLink(EnlMLink->LinkHandle[i - 1]); + EnlMLink->LinkHandle[i - 1] = NULL; + } + } + RETURN_NTSTATUS_IF( + status, + status != STATUS_SUCCESS); + + RETURN_STATUS_SUCCESS(); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void EnlSetPdoWakeSignalCallback( + _In_ ENLP_LINK * EnlLink, + _In_ EVT_ENLP_PDO_WAKE_SIGNAL* evtPdoWakeSignal, + _In_ void* Context) +{ + EnlLink->EvtWakeSignal = evtPdoWakeSignal; + EnlLink->WakeSignalContext = Context; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlArmWake( + _In_ ENLP_LINK * EnlLink +) +{ + EnlLink->ArmedForWake = TRUE; + RtlZeroMemory(&EnlLink->WakeFrame[0], sizeof(EnlLink->WakeFrame)); + EnlLink->WakeFrameSize = 0; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlDisarmWake( + _In_ ENLP_LINK * EnlLink +) +{ + EnlLink->ArmedForWake = FALSE; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +size_t +EnlCopyWakeFrame( + _In_ ENLP_LINK * EnlLink, + _Out_writes_bytes_(BufferSize) unsigned char * Buffer, + _In_ size_t BufferSize +) +{ + if (EnlLink->WakeFrameSize == 0) + { + // There was no wake + return 0; + } + + if (BufferSize < EnlLink->WakeFrameSize) + { + // Wake frame is larger than what we can indicate + return 0; + } + + RtlCopyMemory(Buffer, &EnlLink->WakeFrame[0], EnlLink->WakeFrameSize); + auto const wakeFrameSize = EnlLink->WakeFrameSize; + + // Make sure to erase the wake frame, since the network interface might have + // multiple receive queues + RtlZeroMemory(&EnlLink->WakeFrame[0], EnlLink->WakeFrameSize); + EnlLink->WakeFrameSize = 0; + + return wakeFrameSize; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlMIsPortActive( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex + ) +{ + ULONG i; + + BOOLEAN result = EnlIsPortActive(EnlMLink->LinkHandle[0], PortIndex); + + for (i = 1; i < EnlMLink->LinkCount; i++) + { + NT_FRE_ASSERT(EnlIsPortActive(EnlMLink->LinkHandle[i], PortIndex) == result); + } + + return result; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlMIsLinkActive( + _In_ CONST ENL_MLINK* EnlMLink + ) +{ + ULONG i; + + BOOLEAN result = EnlIsLinkActive(EnlMLink->LinkHandle[0]); + + for (i = 1; i < EnlMLink->LinkCount; i++) + { + NT_FRE_ASSERT(EnlIsLinkActive(EnlMLink->LinkHandle[i]) == result); + } + + return result; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlMActivateLinkPort( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex, + _In_ ENL_INTERRUPT_ROUTINE Interrupt, + _In_ PVOID PortContext + ) +{ + LogInformation(FLAG_DRIVER, L"EnlMLink=%p PortIndex=%u", EnlMLink, PortIndex); + + NTSTATUS status = STATUS_SUCCESS; + ULONG i; + + for (i = 0; i < EnlMLink->LinkCount; i++) + { + status = EnlActivateLinkPort( + EnlMLink->LinkHandle[i], + PortIndex, + Interrupt, + PortContext); + + if (!NT_SUCCESS(status)) + { + break; + } + } + + if (!NT_SUCCESS(status)) + { + for (; i > 0; i--) + { + EnlDeactivateLinkPort(EnlMLink->LinkHandle[i], PortIndex); + } + } + + RETURN_NTSTATUS_IF(status, + status != STATUS_SUCCESS); + + RETURN_STATUS_SUCCESS(); +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlMDeactivateLinkPort( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex + ) +{ + LogInformation(FLAG_DRIVER, L"EnlMLink=%p PortIndex=%u", EnlMLink, PortIndex); + + ULONG i; + + for (i = 0; i < EnlMLink->LinkCount; i++) + { + EnlDeactivateLinkPort(EnlMLink->LinkHandle[i], PortIndex); + } +} + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlMCloseLink( + _Inout_ ENL_MLINK* EnlMLink + ) +{ + LogInformation(FLAG_DRIVER, L"EnlMLink=%p", EnlMLink); + + ULONG i; + + for (i = 0; i < EnlMLink->LinkCount; i++) + { + EnlCloseLink(EnlMLink->LinkHandle[i]); + EnlMLink->LinkHandle[i] = NULL; + } + + EnlMLink->LinkCount = 0; +} diff --git a/network/netadaptercx/netvadapterlibrary/code/enl.h b/network/netadaptercx/netvadapterlibrary/code/enl.h new file mode 100644 index 00000000..2927a582 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/enl.h @@ -0,0 +1,264 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// Emulated Network Link (ENL) definitions +// + +// +// An ENL connects two virtual network adapters directly. Packets sent over +// one adapter are delivered to the other adapter and vice versa. +// +// An ENL is created with a processor index. This processor is used to emulate +// the NIC hardware for the adapters connected by the ENL. +// +// Caller can send packets as NBLs over a given port, and also receive +// incoming packets placed into NBLs over a given port. +// +// ENL indicates tx and rx NBL completions over the target processor(s) +// determined by the RSS indirection table and the hash value for each NBL. +// The current version of the ENL requires a symmetric Toeplitz hash key +// to be used by the system globally so that both directions of a given +// 4-tuple (or 2-tuple) yield the same hash value. ENL currently indicates +// NBL completions by queueing DPCs to the target processor. +// + + +#ifndef _KERNEL_MODE +#define ASSERT(x) NT_ASSERT(x) + +#endif +#include "rtl/KWaitEvent.h" +#include "rtl/KPushLock.h" + +#define ENL_MAX_PROC_COUNT 16 +#define ENLP_PORT_COUNT 2 + +#define TX TRUE +#define RX FALSE + +enum ENL_QUEUE_STATE { + Stopped, + Started + }; + +typedef +VOID +(ENL_INTERRUPT_ROUTINE) ( + _Inout_ PVOID PortContext, + _In_ bool TxRx + ); + +struct ENLP_LINK; +struct DECLSPEC_ALIGN(PAGE_SIZE) ENLP_PORT; +struct ENLP_QUEUE; + +typedef NTSTATUS(EVT_ENLP_PDO_WAKE_SIGNAL)(_In_ void* Context); + +_IRQL_requires_max_(PASSIVE_LEVEL) +ENLP_QUEUE * +EnlCreateQueue( + _In_ NETPACKETQUEUE Queue, + _In_ BOOLEAN Tx + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlDestroyQueue( + _In_ ENLP_QUEUE * QueueContext, + _In_ BOOLEAN Tx + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlRingDoorBell( + _In_ ENLP_QUEUE * QueueContext, + _In_ ULONG EndIndex + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlArmInterrupt( + _In_ ENLP_QUEUE * QueueContext, + _In_ BOOLEAN NotificationEnabled + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlSetPdoWakeSignalCallback( + _In_ ENLP_LINK * EnlLinkHandle, + _In_ EVT_ENLP_PDO_WAKE_SIGNAL* evtPdoWakeSignal, + _In_ void* Context + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlArmWake( + _In_ ENLP_LINK * EnlLinkHandle + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlDisarmWake( + _In_ ENLP_LINK * EnlLinkHandle + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +size_t +EnlCopyWakeFrame( + _In_ ENLP_LINK * EnlLinkHandle, + _Out_writes_bytes_(BufferSize) unsigned char * Buffer, + _In_ size_t BufferSize + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlIsLinkActive( + _In_ ENLP_LINK * EnlLinkHandle + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlIndicateQueueState( + _In_ ENLP_QUEUE * EnlLinkHandle, + _In_ ENL_QUEUE_STATE State + ); + +/////////////////////////////////////////////////////////////////////////////// +// Multi link wrapper APIs // +/////////////////////////////////////////////////////////////////////////////// + +#define ENL_MLINK_MAX 4 + +typedef struct +{ + _Field_range_(1, ENL_MLINK_MAX) ULONG LinkCount; + _Field_size_(LinkCount) ENLP_LINK * LinkHandle[ENL_MLINK_MAX]; +} ENL_MLINK; + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlMCreateLink( + _In_range_(1, ENL_MLINK_MAX)ULONG LinkCount, + _In_reads_(LinkCount) ULONG ProcessorIndex, + _In_ BOOLEAN Poll, + _Out_ ENL_MLINK* EnlMLink + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +BOOLEAN +EnlMIsPortActive( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +EnlMActivateLinkPort( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex, + _In_ ENL_INTERRUPT_ROUTINE Interrupt, + _In_ PVOID PortContext + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +void +EnlMDeactivateLinkPort( + _In_ CONST ENL_MLINK* EnlMLink, + _In_ ULONG PortIndex + ); + +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +EnlMCloseLink( + _Inout_ ENL_MLINK* EnlMLink + ); + +#define ENL_MAXIMUM_WAKE_FRAME_SIZE 1514 + +typedef +_IRQL_requires_max_(PASSIVE_LEVEL) +VOID +(ENLP_ITERATION_ROUTINE) ( + _In_ PVOID IterationContext + ); + +struct ENLP_THREAD_STATE +{ + BOOLEAN PauseRequested{}; + BOOLEAN StopRequested{}; + ENLP_ITERATION_ROUTINE* IterationRoutine{}; + PVOID IterationContext{}; + KAutoEvent *ArmWaitEvent{}; + KAutoEvent ResumeEvent{}; + KAutoEvent PausingEvent{}; + ULONG ProcIndex{}; + ULONG IdealNode{}; + unique_thread Thread{}; +}; + +class NetvQueue; +class NetvRxQueue; +class NetvTxQueue; + +struct ENLP_QUEUE +{ + BOOLEAN TxRx{}; + BOOLEAN Notify{}; + ULONG QueueEnd{}; + ULONG QueueNext{}; + + ENLP_PORT * EnlPortHandle{}; + + BOOLEAN Armed{}; + WDFSPINLOCK Spinlock{}; + KAutoEvent *ArmWaitEvent{}; + + ENL_QUEUE_STATE State{}; + + NetvQueue * Queue{nullptr}; + union { + NetvRxQueue * RxQueue; + NetvTxQueue * TxQueue; + }; + +}; + +struct DECLSPEC_ALIGN(PAGE_SIZE) ENLP_PORT +{ + ENL_INTERRUPT_ROUTINE* Interrupt; + PVOID PortContext; + ULONG TxQueueCount; + ULONG RxQueueCount; + + DECLSPEC_CACHEALIGN + ENLP_QUEUE TxQueue[ENL_MAX_PROC_COUNT]; + + DECLSPEC_CACHEALIGN + ENLP_QUEUE RxQueue[ENL_MAX_PROC_COUNT]; +}; + +struct ENLP_LINK +{ + KPushLock Lock{}; + ULONG64 Ts{}; + ULONG64 BusyTicks{}; + ULONG64 EmptyTicks{}; + BOOLEAN Poll{}; + BOOLEAN InitializePacketLayout{}; + + // + // Power related features. If PowerInterface is NULL none of the other + // fields have meaning + // + EVT_ENLP_PDO_WAKE_SIGNAL* EvtWakeSignal; + void* WakeSignalContext; + BOOLEAN ArmedForWake{}; + unsigned char WakeFrame[ENL_MAXIMUM_WAKE_FRAME_SIZE]; + size_t WakeFrameSize{}; + + KAutoEvent ArmWaitEvent{}; + ENLP_THREAD_STATE EnlThread{}; + ENLP_PORT Ports[ENLP_PORT_COUNT]; +}; +#define MAX_ADAPTER_COUNT 2 +extern ENL_MLINK NetvEnlMLink[MAX_ADAPTER_COUNT / 2]; +C_ASSERT((ENLP_PORT_COUNT & 0x1) == 0); diff --git a/network/netadaptercx/netvadapterlibrary/code/enlthreads.cpp b/network/netadaptercx/netvadapterlibrary/code/enlthreads.cpp new file mode 100644 index 00000000..ffe70d6e --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/enlthreads.cpp @@ -0,0 +1,136 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "pch.hpp" +//#include <ntassert.h> +#include "enlthreads.h" + +#ifdef _KERNEL_MODE +unique_thread::operator bool( + void +) const +{ + return !!NtHandle; +} + +void unique_thread::reset( +) +{ + NtHandle.reset(); + ObHandle.reset(); +} +#endif + +ENL_THREAD +EnlGetCurrentThread( + void +) +{ +#ifdef _KERNEL_MODE + return KeGetCurrentThread(); +#else + return GetCurrentThreadId(); +#endif +} + +_Use_decl_annotations_ +NTSTATUS +EnlThreadCreate( + ENL_START_ROUTINE StartRoutine, + void * Context, + unique_thread & Thread +) +{ +#ifdef _KERNEL_MODE + + unique_zw_handle ntHandle; + unique_pkthread obHandle; + + auto const ntStatus = PsCreateSystemThread( + &ntHandle, + THREAD_ALL_ACCESS, + nullptr, + nullptr, + nullptr, + StartRoutine, + Context); + + if (ntStatus != STATUS_SUCCESS) + { + return ntStatus; + } + + NT_FRE_ASSERT( + NT_SUCCESS( + ObReferenceObjectByHandle( + ntHandle.get(), + THREAD_ALL_ACCESS, + nullptr, + KernelMode, + reinterpret_cast<void **>(&obHandle), + nullptr))); + + Thread.NtHandle = wistd::move(ntHandle); + Thread.ObHandle = wistd::move(obHandle); + +#else + wil::unique_handle thread{ CreateThread(nullptr, 0, StartRoutine, Context, 0, nullptr) }; + + if (!thread) + { + return NTSTATUS_FROM_WIN32(GetLastError()); + } + + Thread = wistd::move(thread); +#endif + + return STATUS_SUCCESS; +} + +void +EnlThreadSetPriority( + unique_thread & Thread, + ENL_THREAD_PRIORITY Priority +) +{ +#ifdef _KERNEL_MODE + // KeSetBasePriorityThread does not take the actual priority, but an increment + // to be added to the current base priority. Calculate this value. + auto const increment = Priority - (LOW_REALTIME_PRIORITY + LOW_PRIORITY) / 2; + KeSetBasePriorityThread(Thread.ObHandle.get(), increment); +#else + SetThreadPriority(Thread.get(), Priority); +#endif +} + +_Use_decl_annotations_ +void +EnlThreadSetAffinity( + PGROUP_AFFINITY GroupAffinity, + PGROUP_AFFINITY PreviousAffinity +) +{ +#ifdef _KERNEL_MODE + KeSetSystemGroupAffinityThread(GroupAffinity, PreviousAffinity); +#else + SetThreadGroupAffinity(GetCurrentThread(), GroupAffinity, PreviousAffinity); +#endif +} + +_Use_decl_annotations_ +void +EnlThreadWaitForTermination( + unique_thread & Thread +) +{ +#ifdef _KERNEL_MODE + KeWaitForSingleObject( + Thread.ObHandle.get(), + KWAIT_REASON::Executive, + KernelMode, + FALSE, + nullptr); +#else + WaitForSingleObject( + Thread.get(), + INFINITE); +#endif +} diff --git a/network/netadaptercx/netvadapterlibrary/code/enlthreads.h b/network/netadaptercx/netvadapterlibrary/code/enlthreads.h new file mode 100644 index 00000000..062d728e --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/enlthreads.h @@ -0,0 +1,119 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#include <wil/resource.h> +// #include <KMacros.h> + +#ifdef _KERNEL_MODE + using ENL_START_ROUTINE = KSTART_ROUTINE; + using ENL_THREAD_ROUTINE_RETURN = VOID; + using ENL_THREAD = PKTHREAD; + // static const EC_THREAD EC_THREAD_INVALID = nullptr; + using ENL_THREAD_PRIORITY = LONG; + // #define EC_INVALID_THREAD_PRIORITY MAXLONG + + using unique_zw_handle = wil::unique_any<HANDLE, decltype(&::ZwClose), &::ZwClose>; + using unique_pkthread = wil::unique_any<PKTHREAD, decltype(&ObfDereferenceObject), &ObfDereferenceObject>; + using unique_pkevent = wil::unique_any<PKEVENT, decltype(&ObfDereferenceObject), &ObfDereferenceObject>; + using unique_completionport = wil::unique_any<void *, decltype(&ObfDereferenceObject), &ObfDereferenceObject>; + + struct unique_thread + { + unique_zw_handle + NtHandle; + + unique_pkthread + ObHandle; + + operator bool( + void + ) const; + + void reset( + ); + }; +#else + +#ifndef NOTHING +#define NOTHING +#endif + +#ifndef AFFINITY_MASK +#define AFFINITY_MASK(n) ((KAFFINITY)1 << (n)) +#endif + +typedef struct _NDTBUS_POWER_INTERFACE_STANDARD +{ +} NDTBUS_POWER_INTERFACE_STANDARD; + +_IRQL_requires_same_ +typedef DWORD (WINAPI ENL_START_ROUTINE)( + LPVOID lpThreadParameter +); +using ENL_THREAD_ROUTINE_RETURN = DWORD; +using ENL_THREAD = DWORD; +// static const EC_THREAD EC_THREAD_INVALID = 0; +using ENL_THREAD_PRIORITY = int; +// #define EC_INVALID_THREAD_PRIORITY THREAD_PRIORITY_ERROR_RETURN +using unique_thread = wil::unique_handle; + +#define KeGetProcessorIndexFromNumber(_processor) (_processor)->Number +#define KeMemoryBarrier() MemoryBarrier() + +inline +NTSTATUS +KeGetProcessorNumberFromIndex ( + _In_ ULONG ProcIndex, + _Out_ PPROCESSOR_NUMBER ProcNumber + ) +{ + ProcNumber->Number = static_cast<UCHAR>(ProcIndex); + ProcNumber->Group = 0; + ProcNumber->Reserved = 0; + + return STATUS_SUCCESS; +} + +inline +VOID +KeQueryNodeActiveAffinity ( + __in USHORT NodeNumber, + __out_opt PGROUP_AFFINITY Affinity, + __out_opt PUSHORT Count +) +{ + UNREFERENCED_PARAMETER(NodeNumber); + UNREFERENCED_PARAMETER(Count); + + GetThreadGroupAffinity(GetCurrentThread(), Affinity); +} +#endif + +ENL_THREAD +EnlGetCurrentThread( + void +); + +NTSTATUS +EnlThreadCreate( + _In_ ENL_START_ROUTINE StartRoutine, + _In_opt_ void * Context, + _Out_ unique_thread & Thread +); + +void +EnlThreadSetPriority( + _In_ unique_thread & Thread, + _In_ ENL_THREAD_PRIORITY Priority +); + +void +EnlThreadSetAffinity( + _In_ PGROUP_AFFINITY GroupAffinity, + _Out_opt_ PGROUP_AFFINITY PreviousAffinity +); + +void +EnlThreadWaitForTermination( + _In_ unique_thread & Thread +); diff --git a/network/netadaptercx/netvadapterlibrary/code/memory.cpp b/network/netadaptercx/netvadapterlibrary/code/memory.cpp new file mode 100644 index 00000000..35a3f2c5 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/memory.cpp @@ -0,0 +1,11 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "pch.hpp" +#include "memory.h" +#include "memory.tmh" + +// for wil::make_unique_nothrow +void* +operator new(size_t s, std::nothrow_t const&) +{ + return operator new(s); +}
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/code/memory.h b/network/netadaptercx/netvadapterlibrary/code/memory.h new file mode 100644 index 00000000..1200c72c --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/memory.h @@ -0,0 +1,4 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#define MAX_RX_BUFFER_SIZE 65535 diff --git a/network/netadaptercx/netvadapterlibrary/code/net/netpacketlibrary.h b/network/netadaptercx/netvadapterlibrary/code/net/netpacketlibrary.h new file mode 100644 index 00000000..b5e34518 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/net/netpacketlibrary.h @@ -0,0 +1,85 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include <net/virtualaddress.h> + +// +// Following are some helper APIs for common ring manipulations. +// They are all implemented using iterator +// + +inline +SIZE_T +GetTxPacketDataLength( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + SIZE_T length = 0; + + for (NET_RING_FRAGMENT_ITERATOR fi = NetPacketIteratorGetFragments(Iterator); + NetFragmentIteratorHasAny(&fi); + NetFragmentIteratorAdvance(&fi)) + { + NET_FRAGMENT* fragment = NetFragmentIteratorGetFragment(&fi); + length += (SIZE_T)fragment->ValidLength; + } + + return length; +} + +inline +VOID +CompleteTxPacketsBatch( + _In_ NET_RING_COLLECTION const* Rings, + _In_ UINT32 BatchSize +) +{ + UINT32 packetCount = 0; + + NET_RING_PACKET_ITERATOR pi = NetRingGetDrainPackets(Rings); + + while (NetPacketIteratorHasAny(&pi)) + { + NET_PACKET* packet = NetPacketIteratorGetPacket(&pi); + + // this function uses Scratch field as the bit for testing completion + if (!packet->Scratch) + { + break; + } + + packetCount++; + + NET_RING_FRAGMENT_ITERATOR fi = NetPacketIteratorGetFragments(&pi); + NetFragmentIteratorAdvanceToTheEnd(&fi); + + NetPacketIteratorAdvance(&pi); + + if (packetCount >= BatchSize) + { + NetPacketIteratorSet(&pi); + Rings->Rings[NetRingTypeFragment]->BeginIndex = NetFragmentIteratorGetIndex(&fi); + } + } +} + +inline +void +CancelRxPackets( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING_PACKET_ITERATOR pi = NetRingGetAllPackets(Rings); + + for (; NetPacketIteratorHasAny(&pi); NetPacketIteratorAdvance(&pi)) + { + NetPacketIteratorGetPacket(&pi)->Ignore = 1; + } + + NetPacketIteratorSet(&pi); + + NET_RING_FRAGMENT_ITERATOR fi = NetRingGetAllFragments(Rings); + NetFragmentIteratorAdvanceToTheEnd(&fi); + NetFragmentIteratorSet(&fi); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/net/netringiterator.h b/network/netadaptercx/netvadapterlibrary/code/net/netringiterator.h new file mode 100644 index 00000000..fb010751 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/net/netringiterator.h @@ -0,0 +1,281 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include <net/ringcollection.h> + +typedef struct _NET_RING_ITERATOR +{ + + NET_RING_COLLECTION const* + Rings; + + UINT32* const + IndexToSet; + + UINT32 + Index; + + UINT32 const + End; + +} NET_RING_ITERATOR; + +typedef struct _NET_RING_PACKET_ITERATOR +{ + + NET_RING_ITERATOR + Iterator; + +} NET_RING_PACKET_ITERATOR; + +typedef struct _NET_RING_FRAGMENT_ITERATOR +{ + + NET_RING_ITERATOR + Iterator; + +} NET_RING_FRAGMENT_ITERATOR; + + +inline +NET_RING_PACKET_ITERATOR +NetRingGetPostPackets( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypePacket]; + NET_RING_PACKET_ITERATOR iterator = { + Rings, &ring->NextIndex, ring->NextIndex, ring->EndIndex, + }; + + return iterator; +} + +inline +NET_RING_PACKET_ITERATOR +NetRingGetDrainPackets( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypePacket]; + NET_RING_PACKET_ITERATOR iterator = { + Rings, &ring->BeginIndex, ring->BeginIndex, ring->NextIndex, + }; + + return iterator; +} + +inline +NET_RING_PACKET_ITERATOR +NetRingGetAllPackets( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypePacket]; + NET_RING_PACKET_ITERATOR iterator = { + Rings, &ring->BeginIndex, ring->BeginIndex, ring->EndIndex, + }; + + return iterator; +} + +inline +NET_PACKET* +NetPacketIteratorGetPacket( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + return NetRingGetPacketAtIndex( + Iterator->Iterator.Rings->Rings[NetRingTypePacket], + Iterator->Iterator.Index); +} + +inline +UINT32 +NetPacketIteratorGetIndex( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + return Iterator->Iterator.Index; +} + +inline +BOOLEAN +NetPacketIteratorHasAny( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + return Iterator->Iterator.Index != Iterator->Iterator.End; +} + +inline +UINT32 +NetPacketIteratorGetCount( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + NET_RING const* ring = Iterator->Iterator.Rings->Rings[NetRingTypePacket]; + + return (Iterator->Iterator.End - Iterator->Iterator.Index) & ring->ElementIndexMask; +} + +inline +void +NetPacketIteratorAdvance( + _In_ NET_RING_PACKET_ITERATOR* Iterator +) +{ + Iterator->Iterator.Index = NetRingIncrementIndex( + Iterator->Iterator.Rings->Rings[NetRingTypePacket], + Iterator->Iterator.Index); +} + +inline +void +NetPacketIteratorAdvanceToTheEnd( + _In_ NET_RING_PACKET_ITERATOR* Iterator +) +{ + Iterator->Iterator.Index = Iterator->Iterator.End; +} + +inline +void +NetPacketIteratorSet( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + *Iterator->Iterator.IndexToSet + = Iterator->Iterator.Index; +} + + +inline +NET_RING_FRAGMENT_ITERATOR +NetPacketIteratorGetFragments( + _In_ NET_RING_PACKET_ITERATOR const* Iterator +) +{ + NET_RING const* ring = Iterator->Iterator.Rings->Rings[NetRingTypeFragment]; + NET_PACKET const* packet = NetPacketIteratorGetPacket(Iterator); + UINT32 const end = NetRingIncrementIndex(ring, + packet->FragmentIndex + packet->FragmentCount - 1); + NET_RING_FRAGMENT_ITERATOR iterator = { + Iterator->Iterator.Rings, NULL, packet->FragmentIndex, end, + }; + + return iterator; +} + +inline +NET_RING_FRAGMENT_ITERATOR +NetRingGetPostFragments( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypeFragment]; + NET_RING_FRAGMENT_ITERATOR iterator = { + Rings, &ring->NextIndex, ring->NextIndex, ring->EndIndex, + }; + + return iterator; +} + +inline +NET_RING_FRAGMENT_ITERATOR +NetRingGetDrainFragments( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypeFragment]; + NET_RING_FRAGMENT_ITERATOR iterator = { + Rings, &ring->BeginIndex, ring->BeginIndex, ring->NextIndex, + }; + + return iterator; +} + +inline +NET_RING_FRAGMENT_ITERATOR +NetRingGetAllFragments( + _In_ NET_RING_COLLECTION const* Rings +) +{ + NET_RING* ring = Rings->Rings[NetRingTypeFragment]; + NET_RING_FRAGMENT_ITERATOR iterator = { + Rings, &ring->BeginIndex, ring->BeginIndex, ring->EndIndex, + }; + + return iterator; +} + +inline +NET_FRAGMENT* +NetFragmentIteratorGetFragment( + _In_ NET_RING_FRAGMENT_ITERATOR const* Iterator +) +{ + return NetRingGetFragmentAtIndex( + Iterator->Iterator.Rings->Rings[NetRingTypeFragment], + Iterator->Iterator.Index); +} + +inline +UINT32 +NetFragmentIteratorGetIndex( + _In_ NET_RING_FRAGMENT_ITERATOR const* Iterator +) +{ + return Iterator->Iterator.Index; +} + +inline +BOOLEAN +NetFragmentIteratorHasAny( + _In_ NET_RING_FRAGMENT_ITERATOR const* Iterator +) +{ + return Iterator->Iterator.Index != Iterator->Iterator.End; +} + +inline +UINT32 +NetFragmentIteratorGetCount( + _In_ NET_RING_FRAGMENT_ITERATOR const* Iterator +) +{ + NET_RING const* ring = Iterator->Iterator.Rings->Rings[NetRingTypeFragment]; + + return (Iterator->Iterator.End - Iterator->Iterator.Index) & ring->ElementIndexMask; +} + +inline +void +NetFragmentIteratorAdvance( + _In_ NET_RING_FRAGMENT_ITERATOR* Iterator +) +{ + Iterator->Iterator.Index = NetRingIncrementIndex( + Iterator->Iterator.Rings->Rings[NetRingTypeFragment], + Iterator->Iterator.Index); +} + +inline +void +NetFragmentIteratorAdvanceToTheEnd( + _In_ NET_RING_FRAGMENT_ITERATOR* Iterator +) +{ + Iterator->Iterator.Index = Iterator->Iterator.End; +} + +inline +void +NetFragmentIteratorSet( + _In_ NET_RING_FRAGMENT_ITERATOR const* Iterator +) +{ + *(Iterator->Iterator.IndexToSet) + = Iterator->Iterator.Index; +} diff --git a/network/netadaptercx/netvadapterlibrary/code/net/umxfilter.h b/network/netadaptercx/netvadapterlibrary/code/net/umxfilter.h new file mode 100644 index 00000000..a6a019e4 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/net/umxfilter.h @@ -0,0 +1,268 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + xfilter.h + +Abstract: + + Header file for the address filtering library for NDIS MAC's. + +Author: + +Environment: + +Notes: + + None. + +Revision History: + +--*/ + +#ifndef _X_FILTER_DEFS_ +#define _X_FILTER_DEFS_ + +#pragma once + +#define ETH_LENGTH_OF_ADDRESS 6 + + +// +// ZZZ This is a little-endian specific check. +// +#define ETH_IS_MULTICAST(Address) \ + (BOOLEAN)(((PUCHAR)(Address))[0] & ((UCHAR)0x01)) + + +// +// Check whether an address is broadcast. +// +#define ETH_IS_BROADCAST(Address) \ + ((((PUCHAR)(Address))[0] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[1] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[2] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[3] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[4] == ((UCHAR)0xff)) && (((PUCHAR)(Address))[5] == ((UCHAR)0xff))) + + +// +// This macro will compare network addresses. +// +// A - Is a network address. +// +// B - Is a network address. +// +// Result - The result of comparing two network address. +// +// Result < 0 Implies the B address is greater. +// Result > 0 Implies the A element is greater. +// Result = 0 Implies equality. +// +// Note that this is an arbitrary ordering. There is not +// defined relation on network addresses. This is ad-hoc! +// +// +#define ETH_COMPARE_NETWORK_ADDRESSES(_A, _B, _Result) \ +{ \ + if (*(ULONG UNALIGNED *)&(_A)[2] > \ + *(ULONG UNALIGNED *)&(_B)[2]) \ + { \ + *(_Result) = 1; \ + } \ + else if (*(ULONG UNALIGNED *)&(_A)[2] < \ + *(ULONG UNALIGNED *)&(_B)[2]) \ + { \ + *(_Result) = (UINT)-1; \ + } \ + else if (*(USHORT UNALIGNED *)(_A) > \ + *(USHORT UNALIGNED *)(_B)) \ + { \ + *(_Result) = 1; \ + } \ + else if (*(USHORT UNALIGNED *)(_A) < \ + *(USHORT UNALIGNED *)(_B)) \ + { \ + *(_Result) = (UINT)-1; \ + } \ + else \ + { \ + *(_Result) = 0; \ + } \ +} + +// +// This macro will compare network addresses. +// +// A - Is a network address. +// +// B - Is a network address. +// +// Result - The result of comparing two network address. +// +// Result != 0 Implies inequality. +// Result == 0 Implies equality. +// +// +#define ETH_COMPARE_NETWORK_ADDRESSES_EQ(_A,_B, _Result) \ +{ \ + if ((*(ULONG UNALIGNED *)&(_A)[2] == \ + *(ULONG UNALIGNED *)&(_B)[2]) && \ + (*(USHORT UNALIGNED *)(_A) == \ + *(USHORT UNALIGNED *)(_B))) \ + { \ + *(_Result) = 0; \ + } \ + else \ + { \ + *(_Result) = 1; \ + } \ +} + + +// +// This macro is used to copy from one network address to +// another. +// +#define ETH_COPY_NETWORK_ADDRESS(_D, _S) \ +{ \ + *((ULONG UNALIGNED *)(_D)) = *((ULONG UNALIGNED *)(_S)); \ + *((USHORT UNALIGNED *)((UCHAR *)(_D)+4)) = *((USHORT UNALIGNED *)((UCHAR *)(_S)+4)); \ +} + +#define TR_LENGTH_OF_FUNCTIONAL 4 +#define TR_LENGTH_OF_ADDRESS 6 + + +// +// Only the low 32 bits of the functional/group address +// are needed since the upper 16 bits is always c0-00. +// +typedef ULONG TR_FUNCTIONAL_ADDRESS; +typedef ULONG TR_GROUP_ADDRESS; + + +#define TR_IS_NOT_DIRECTED(_Address, _Result) \ +{ \ + *(_Result) = (BOOLEAN)((_Address)[0] & 0x80); \ +} + +#define TR_IS_FUNCTIONAL(_Address, _Result) \ +{ \ + *(_Result) = (BOOLEAN)(((_Address)[0] & 0x80) && \ + !((_Address)[2] & 0x80)); \ +} + +// +// +#define TR_IS_GROUP(_Address, _Result) \ +{ \ + *(_Result) = (BOOLEAN)((_Address)[0] & (_Address)[2] & 0x80); \ +} + +// +// +#define TR_IS_SOURCE_ROUTING(_Address, _Result) \ +{ \ + *(_Result) = (BOOLEAN)((_Address)[0] & 0x80); \ +} + +// +// Check for NDIS_PACKET_TYPE_MAC_FRAME +// +#define TR_IS_MAC_FRAME(_PacketHeader) ((((PUCHAR)_PacketHeader)[1] & 0xFC) == 0) + + +// +// Check whether an address is broadcast. This is a little-endian check. +// +#define TR_IS_BROADCAST(_Address, _Result) \ +{ \ + *(_Result) = (BOOLEAN)(((*(UNALIGNED USHORT *)&(_Address)[0] == 0xFFFF) || \ + (*(UNALIGNED USHORT *)&(_Address)[0] == 0x00C0)) && \ + (*(UNALIGNED ULONG *)&(_Address)[2] == 0xFFFFFFFF));\ +} + + +// +// This macro will compare network addresses. +// +// A - Is a network address. +// +// B - Is a network address. +// +// Result - The result of comparing two network address. +// +// Result < 0 Implies the B address is greater. +// Result > 0 Implies the A element is greater. +// Result = 0 Implies equality. +// +// Note that this is an arbitrary ordering. There is not +// defined relation on network addresses. This is ad-hoc! +// +// +#define TR_COMPARE_NETWORK_ADDRESSES(_A, _B, _Result) \ +{ \ + if (*(ULONG UNALIGNED *)&(_A)[2] > \ + *(ULONG UNALIGNED *)&(_B)[2]) \ + { \ + *(_Result) = 1; \ + } \ + else if (*(ULONG UNALIGNED *)&(_A)[2] < \ + *(ULONG UNALIGNED *)&(_B)[2]) \ + { \ + *(_Result) = (UINT)-1; \ + } \ + else if (*(USHORT UNALIGNED *)(_A) > \ + *(USHORT UNALIGNED *)(_B)) \ + { \ + *(_Result) = 1; \ + } \ + else if (*(USHORT UNALIGNED *)(_A) < \ + *(USHORT UNALIGNED *)(_B)) \ + { \ + *(_Result) = (UINT)-1; \ + } \ + else \ + { \ + *(_Result) = 0; \ + } \ +} + +// +// This macro will compare network addresses. +// +// A - Is a network address. +// +// B - Is a network address. +// +// Result - The result of comparing two network address. +// +// Result != 0 Implies inequality. +// Result == 0 Implies equality. +// +// +#define TR_COMPARE_NETWORK_ADDRESSES_EQ(_A, _B, _Result) \ +{ \ + if ((*(ULONG UNALIGNED *)&(_A)[2] == *(ULONG UNALIGNED *)&(_B)[2]) && \ + (*(USHORT UNALIGNED *)&(_A)[0] == *(USHORT UNALIGNED *)&(_B)[0])) \ + { \ + *(_Result) = 0; \ + } \ + else \ + { \ + *(_Result) = 1; \ + } \ +} + + +// +// This macro is used to copy from one network address to +// another. +// +#define TR_COPY_NETWORK_ADDRESS(_D, _S) \ +{ \ + *((ULONG UNALIGNED *)(_D)) = *((ULONG UNALIGNED *)(_S)); \ + *((USHORT UNALIGNED *)((UCHAR *)(_D)+4)) = \ + *((USHORT UNALIGNED *)((UCHAR *)(_S)+4)); \ +} + +#endif // _X_FILTER_DEFS_ diff --git a/network/netadaptercx/netvadapterlibrary/code/pch.hpp b/network/netadaptercx/netvadapterlibrary/code/pch.hpp new file mode 100644 index 00000000..cf2f0f22 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/pch.hpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once + +#include <initguid.h> + +#ifndef _KERNEL_MODE +// This is a user-mode driver +#include <windows.h> + +#else +// This is a kernel-mode driver +#include <ntddk.h> +#define NTSTRSAFE_LIB +#include <ntstrsafe.h> +#endif + +// This is a common WDF header (for both KMDF and UMDF) +#include <wdf.h> + +#include <netadaptercx.h> +//#include <wdftriage.h> +#include "net/netringiterator.h" +#include "net/netpacketlibrary.h" +#include <net/rsc.h> +#include <net/gso.h> +#include <net/checksum.h> +#include <net/databuffer.h> +#include <net/returncontext.h> + +#include "enlthreads.h" +#include "enl.h" + +#include "trace.h" + diff --git a/network/netadaptercx/netvadapterlibrary/code/queue.cpp b/network/netadaptercx/netvadapterlibrary/code/queue.cpp new file mode 100644 index 00000000..667d59f7 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/queue.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" + +#include <net/ringcollection.h> + +#include "queue.h" + +NetvQueue::NetvQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter, + NET_RING_COLLECTION const * Rings +) + : m_handle{Handle} + , m_adapter{Adapter} + , m_rings{Rings} +{ +} + +NET_RING * +NetvQueue::GetPacketRing( + void +) +{ + return NetRingCollectionGetPacketRing(m_rings); +} + +NET_RING * +NetvQueue::GetFragmentRing( + void +) +{ + return NetRingCollectionGetFragmentRing(m_rings); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/queue.h b/network/netadaptercx/netvadapterlibrary/code/queue.h new file mode 100644 index 00000000..becb72ce --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/queue.h @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#pragma once + +class NetvAdapter; +struct ENLP_QUEUE; + +class NetvQueue +{ + +public: + + NetvQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter, + NET_RING_COLLECTION const * Rings + ); + + NET_RING * + GetPacketRing( + void + ); + + NET_RING * + GetFragmentRing( + void + ); + + NETPACKETQUEUE const + m_handle{WDF_NO_HANDLE}; + + NetvAdapter & + m_adapter; + + NET_RING_COLLECTION const * + m_rings; + + ENLP_QUEUE * + EnlQueueHandle; + +}; diff --git a/network/netadaptercx/netvadapterlibrary/code/rtl/KCriticalRegion.h b/network/netadaptercx/netvadapterlibrary/code/rtl/KCriticalRegion.h new file mode 100644 index 00000000..0bbedadb --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rtl/KCriticalRegion.h @@ -0,0 +1,67 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#include <KMacros.h> + +class KCriticalRegion +{ +public: + + PAGED KCriticalRegion() : m_Entered(false) { } + + PAGED ~KCriticalRegion() { if (m_Entered) Leave(); } + + KCriticalRegion(KCriticalRegion &) = delete; + KCriticalRegion &operator=(KCriticalRegion &) = delete; + + PAGED void Enter() + { + ASSERT(m_Entered == false); + UnbalancedEnter(); + m_Entered = true; + } + + PAGED void Leave() + { + ASSERT(m_Entered == true); + m_Entered = false; + UnbalancedLeave(); + } + + static PAGED void UnbalancedEnter() + { +#if _KERNEL_MODE + KeEnterCriticalRegion(); +#endif + } + + static PAGED void UnbalancedLeave() + { +#if _KERNEL_MODE + KeLeaveCriticalRegion(); +#endif + } + +private: + + bool m_Entered; +}; + +struct KDefaultRegion +{ + void Enter() { } + void Leave() { } +}; + +struct KIrqlRegion +{ + KIrqlRegion() { } + ~KIrqlRegion() { } + + void Enter() { } + void Leave() { } + + KIRQL m_OldIrql; +}; + + diff --git a/network/netadaptercx/netvadapterlibrary/code/rtl/KLockHolder.h b/network/netadaptercx/netvadapterlibrary/code/rtl/KLockHolder.h new file mode 100644 index 00000000..d398f137 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rtl/KLockHolder.h @@ -0,0 +1,114 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#include <KCriticalRegion.h> +#include <KPushLock.h> + +class KRTL_CLASS KLockHolder +{ +private: + + enum { Unlocked, Shared, Exclusive } m_State; + +public: + + PAGED KLockHolder(KPushLockBase &lock) : m_Lock(lock), m_State(Unlocked) { } + PAGED ~KLockHolder() + { + switch (m_State) + { + case Shared: + ReleaseShared(); + break; + case Exclusive: + ReleaseExclusive(); + break; + } + } + + KLockHolder(KLockHolder &) = delete; + KLockHolder &operator=(KLockHolder &) = delete; + + _IRQL_requires_(PASSIVE_LEVEL) + PAGED void AcquireShared() + { + m_Region.Enter(); + ASSERT(m_State == Unlocked); + m_Lock.AcquireShared(); + m_State = Shared; + } + + _IRQL_requires_(PASSIVE_LEVEL) + PAGED void ReleaseShared() + { + ASSERT(m_State == Shared); + m_Lock.ReleaseShared(); + m_State = Unlocked; + m_Region.Leave(); + } + + _IRQL_requires_(PASSIVE_LEVEL) + PAGED void AcquireExclusive() + { + m_Region.Enter(); + ASSERT(m_State == Unlocked); + m_Lock.AcquireExclusive(); + m_State = Exclusive; + } + + _IRQL_requires_(PASSIVE_LEVEL) + PAGED void ReleaseExclusive() + { + ASSERT(m_State == Exclusive); + m_Lock.ReleaseExclusive(); + m_State = Unlocked; + m_Region.Leave(); + } + +private: + + KPushLockBase &m_Lock; + KCriticalRegion m_Region; +}; + +class KRTL_CLASS KLockThisShared : protected KLockHolder +{ +public: + + PAGED KLockThisShared(KPushLockBase &lock) : KLockHolder(lock) + { + AcquireShared(); + } + + PAGED void Acquire() + { + AcquireShared(); + } + + PAGED void Release() + { + ReleaseShared(); + } +}; + +class KRTL_CLASS KLockThisExclusive : protected KLockHolder +{ +public: + + PAGED KLockThisExclusive(KPushLockBase &lock) : KLockHolder(lock) + { + AcquireExclusive(); + } + + PAGED void Acquire() + { + AcquireExclusive(); + } + + PAGED void Release() + { + ReleaseExclusive(); + } +}; + + diff --git a/network/netadaptercx/netvadapterlibrary/code/rtl/KMacros.h b/network/netadaptercx/netvadapterlibrary/code/rtl/KMacros.h new file mode 100644 index 00000000..631c08bf --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rtl/KMacros.h @@ -0,0 +1,84 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include <wil/common.h> + +#ifdef _KERNEL_MODE + +// nullptr_t is normally automatically defined by the CRT headers, but it +// doesn't get included by kernel code. +namespace std { typedef decltype(__nullptr) nullptr_t; } +using ::std::nullptr_t; + +// The stddef.h used for kernel code has the old offsetof macro. +// Let's use the new one instead. +#undef offsetof +#define offsetof(s,m) __builtin_offsetof(s,m) + +#endif // _KERNEL_MODE + +#define BEGIN_MACRO do { +#define END_MACRO } while (0) + +#ifdef _KERNEL_MODE +#define CODE_SEG(segment) __declspec(code_seg(segment)) +#else +#define CODE_SEG(segment) +#endif + +#ifndef KRTL_PAGE_SEGMENT +# define KRTL_PAGE_SEGMENT "PAGE" +#endif +#ifndef KRTL_INIT_SEGMENT +# define KRTL_INIT_SEGMENT "INIT" +#endif +#ifndef KRTL_NONPAGED_SEGMENT +# define KRTL_NONPAGED_SEGMENT ".text" +#endif + +/// Use on pageable functions. +#define PAGED CODE_SEG(KRTL_PAGE_SEGMENT) _IRQL_always_function_max_(PASSIVE_LEVEL) + +/// Use on pageable functions, where you don't want the SAL IRQL annotation to say PASSIVE_LEVEL. +#define PAGEDX CODE_SEG(KRTL_PAGE_SEGMENT) + +/// Use on code in the INIT segment. (Code is discarded after DriverEntry returns.) +#define INITCODE CODE_SEG(KRTL_INIT_SEGMENT) + +/// Use on code that must always be locked in memory. +#define NONPAGED CODE_SEG(KRTL_NONPAGED_SEGMENT) _IRQL_requires_max_(DISPATCH_LEVEL) + +/// Use on code that must always be locked in memory, where you don't want SAL IRQL annotations. +#define NONPAGEDX CODE_SEG(KRTL_NONPAGED_SEGMENT) + +#ifndef _KERNEL_MODE + +#ifndef PAGED_CODE +#define PAGED_CODE() (void)0 +#endif // PAGED_CODE + +#endif // _KERNEL_MODE + +/// Use on classes or structs. Class member functions & compiler-generated code +/// will default to the PAGE segment. You can override any member function with `NONPAGED`. +#define KRTL_CLASS CODE_SEG(KRTL_PAGE_SEGMENT) __declspec(empty_bases) + +/// Use on classes or structs. Class member functions & compiler-generated code +/// will default to the NONPAGED segment. You can override any member function with `PAGED`. +#define KRTL_CLASS_DPC_ALLOC __declspec(empty_bases) + +enum CallRunMode +{ + // This call should complete synchronously on the current thread + RunSynchronous, + // This call should return immediately, and complete the operation in a background thread + RunAsynchronous, + // This call can return immediately, OR complete synchronously + // (Use this if you're running on a workitem thread already, and you + // don't mind if the callee uses your thread to do its work, but you + // can tolerate the call completing asynchronously if the callee doesn't + // need your thread.) + RunAsynchronousButOkayToBlock, +}; + diff --git a/network/netadaptercx/netvadapterlibrary/code/rtl/KPushLock.h b/network/netadaptercx/netvadapterlibrary/code/rtl/KPushLock.h new file mode 100644 index 00000000..c589866c --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rtl/KPushLock.h @@ -0,0 +1,147 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include <KMacros.h> +#include <KCriticalRegion.h> + +typedef struct _KTHREAD *PKTHREAD; +// Copyright (C) Microsoft Corporation. All rights reserved. + +class KPushLockBase +{ +public: + + KPushLockBase() = default; + KPushLockBase(KPushLockBase &) = delete; + KPushLockBase & operator=(KPushLockBase &) = delete; + + PAGED + void + KPushLockBase::AcquireShared() + { +#ifdef _KERNEL_MODE + ExAcquirePushLockShared(&m_Lock); +#else + AcquireSRWLockShared(&m_Lock); +#endif + } + + PAGED + void + KPushLockBase::ReleaseShared() + { +#ifdef _KERNEL_MODE + ExReleasePushLockShared(&m_Lock); +#else + ReleaseSRWLockShared(&m_Lock); +#endif + } + + PAGED + void + KPushLockBase::AcquireExclusive() + { +#ifdef _KERNEL_MODE + ExAcquirePushLockExclusive(&m_Lock); +#if DBG + m_ExclusiveOwner = KeGetCurrentThread(); +#endif +#else + AcquireSRWLockExclusive(&m_Lock); +#endif + + } + + PAGED + void + KPushLockBase::ReleaseExclusive() + { +#if DBG + m_ExclusiveOwner = nullptr; +#endif +#ifdef _KERNEL_MODE + ExReleasePushLockExclusive(&m_Lock); +#else + ReleaseSRWLockExclusive(&m_Lock); +#endif + } + + PAGED + void + KPushLockBase::AssertLockHeld() + { +#ifdef _KERNEL_MODE + WIN_ASSERT(m_ExclusiveOwner == KeGetCurrentThread()); +#endif + } + + PAGED + void + KPushLockBase::AssertLockNotHeld() + { +#if DBG && defined(_KERNEL_MODE) + WIN_ASSERT(m_ExclusiveOwner != KeGetCurrentThread()); +#endif + } + +protected: + + PAGED + void + KPushLockBase::InitializeInner() + { +#ifdef _KERNEL_MODE + ExInitializePushLock(&m_Lock); +#else + InitializeSRWLock(&m_Lock); +#endif +#if DBG + m_ExclusiveOwner = nullptr; +#endif + } + +private: + +#ifdef _KERNEL_MODE + EX_PUSH_LOCK m_Lock; +#else + SRWLOCK m_Lock; +#endif + +#if DBG + PKTHREAD m_ExclusiveOwner; +#endif +}; + +class KPushLock : public KPushLockBase +{ +public: + + PAGED + KPushLock::KPushLock() noexcept + { + InitializeInner(); + } + + + + PAGED + KPushLock::~KPushLock() + { + AssertLockNotHeld(); + } +}; + +class KPushLockManualConstruct : public KPushLockBase +{ +public: + + PAGED + void + KPushLockManualConstruct::Initialize() + { + InitializeInner(); + } +}; + diff --git a/network/netadaptercx/netvadapterlibrary/code/rtl/KWaitEvent.h b/network/netadaptercx/netvadapterlibrary/code/rtl/KWaitEvent.h new file mode 100644 index 00000000..124f416e --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rtl/KWaitEvent.h @@ -0,0 +1,172 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#include <KMacros.h> + +#if _KERNEL_MODE +typedef wistd::integral_constant<EVENT_TYPE, SynchronizationEvent> auto_reset_event_t; +#else +typedef wistd::integral_constant<bool, false> auto_reset_event_t; +#endif + +#if _KERNEL_MODE +typedef wistd::integral_constant<EVENT_TYPE, NotificationEvent> manual_reset_event_t; +#else +typedef wistd::integral_constant<bool, true> manual_reset_event_t; +#endif + +#define WIN_VERIFY NT_VERIFY +#define WIN_ASSERT NT_ASSERT + +template<typename TEventType> +class KWaitEventBase +{ +public: + + KWaitEventBase() = default; + +#ifdef _KERNEL_MODE + NONPAGED ~KWaitEventBase() = default; +#else + NONPAGED ~KWaitEventBase() + { + WIN_ASSERT(m_event == nullptr); + } +#endif + + KWaitEventBase(KWaitEventBase &) = delete; + KWaitEventBase(KWaitEventBase &&) = delete; + KWaitEventBase & operator=(KWaitEventBase &) = delete; + KWaitEventBase & operator=(KWaitEventBase &&) = delete; + + _IRQL_requires_max_(DISPATCH_LEVEL) void Set() + { +#if _KERNEL_MODE + KeSetEvent(&m_event, 0, false); +#else + WIN_VERIFY(SetEvent(m_event)); +#endif + } + + _IRQL_requires_max_(DISPATCH_LEVEL) void Clear() + { +#if _KERNEL_MODE + KeClearEvent(&m_event); +#else + WIN_VERIFY(ResetEvent(m_event)); +#endif + } + + PAGED void Wait() + { +#if _KERNEL_MODE + // Not used at runtime, but might be useful during debugging + volatile LARGE_INTEGER SystemTime; + KeQuerySystemTime(const_cast<LARGE_INTEGER*>(&SystemTime)); + + NTSTATUS NtStatus = KeWaitForSingleObject( + &m_event, Executive, KernelMode, FALSE, nullptr); + NT_VERIFY(NtStatus == STATUS_SUCCESS); +#else + ULONG r = WaitForSingleObject(m_event, INFINITE); + WIN_VERIFY(r == NO_ERROR); +#endif + } + + PAGED bool Test() + { +#if _KERNEL_MODE + return !!KeReadStateEvent(&m_event); +#else + ULONG r = WaitForSingleObject(m_event, 0); + WIN_VERIFY(r == WAIT_TIMEOUT || r == WAIT_OBJECT_0); + return (r == WAIT_OBJECT_0); +#endif + } + + NONPAGED bool TestNP() + { +#if _KERNEL_MODE + return !!KeReadStateEvent(&m_event); +#else + ULONG r = WaitForSingleObject(m_event, 0); + WIN_VERIFY(r == WAIT_TIMEOUT || r == WAIT_OBJECT_0); + return (r == WAIT_OBJECT_0); +#endif + } + +protected: + + PAGED void InitializeBase() + { +#if _KERNEL_MODE + KeInitializeEvent(&m_event, TEventType(), FALSE); +#else + m_event = CreateEventW(nullptr, TEventType(), false, nullptr); + WIN_VERIFY(m_event); +#endif + } + + NONPAGED void CleanupBase() + { +#ifndef _KERNEL_MODE + CloseHandle(m_event); + m_event = nullptr; +#endif + } + +private: + +#if _KERNEL_MODE + KEVENT m_event; +#else + HANDLE m_event; +#endif + +}; + +class KWaitEvent : public KWaitEventBase<manual_reset_event_t> +{ +public: + + PAGED KWaitEvent() noexcept + { + InitializeBase(); + } + + NONPAGED ~KWaitEvent() + { + CleanupBase(); + } +}; + +class KWaitEventManualConstruct : public KWaitEventBase<manual_reset_event_t> +{ +public: + + PAGED void Initialize() + { + InitializeBase(); + } + + PAGED void Cleanup() + { + CleanupBase(); + } +}; + + +class KAutoEvent : public KWaitEventBase<auto_reset_event_t> +{ +public: + + PAGED KAutoEvent() noexcept + { + InitializeBase(); + } + + NONPAGED ~KAutoEvent() + { + CleanupBase(); + } +}; diff --git a/network/netadaptercx/netvadapterlibrary/code/rxqueue.cpp b/network/netadaptercx/netvadapterlibrary/code/rxqueue.cpp new file mode 100644 index 00000000..6eed638c --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rxqueue.cpp @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" +#include "netvadapter.h" +#include "rxqueue.h" +#include "memory.h" + +static +void +CheckForWakeFrame( + NetvRxQueue * rx +) +{ + NET_RING_FRAGMENT_ITERATOR fi = NetRingGetAllFragments(rx->m_rings); + + if (! NetFragmentIteratorHasAny(&fi)) + { + return; + } + + auto *fragment = NetFragmentIteratorGetFragment(&fi); + auto *rxVirtualAddress = NetExtensionGetFragmentVirtualAddress( + &rx->VirtualAddressExtension, + NetFragmentIteratorGetIndex(&fi)); + + auto *fragmentBuffer = reinterpret_cast<unsigned char *>(rxVirtualAddress->VirtualAddress) + fragment->Offset; + + fragment->ValidLength = EnlCopyWakeFrame( + NetvEnlMLink[rx->m_adapter.EnlIndex].LinkHandle[0], + fragmentBuffer, + fragment->Capacity); + + // If there was a pending wake frame mark this fragment as complete, the normal advance code will get to it + fragment->Scratch = fragment->ValidLength > 0 ? 1 : 0; + + rx->CheckedWakeFrame = true; +} + + +NetvRxQueue::NetvRxQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter +) + : NetvQueue{Handle, Adapter, NetRxQueueGetRingCollection(Handle)} +{ + NET_EXTENSION_QUERY extension; + + NET_EXTENSION_QUERY_INIT( + &extension, + NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME, + NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1, + NetExtensionTypeFragment); + + NetRxQueueGetExtension(m_handle, &extension, &VirtualAddressExtension); + + NET_EXTENSION_QUERY_INIT( + &extension, + NET_PACKET_EXTENSION_RSC_NAME, + NET_PACKET_EXTENSION_RSC_VERSION_2, + NetExtensionTypePacket); + + NetRxQueueGetExtension(m_handle, &extension, &UdpRscExtension); + + NET_EXTENSION_QUERY_INIT( + &extension, + NET_PACKET_EXTENSION_CHECKSUM_NAME, + NET_PACKET_EXTENSION_CHECKSUM_VERSION_1, + NetExtensionTypePacket); + + NetRxQueueGetExtension(m_handle, &extension, &RxXSumExtension); + + EnlQueueHandle = EnlCreateQueue(Handle, RX); +} + +_Use_decl_annotations_ +void +NetvRxQueue::Destroy( + void +) +{ + EnlDestroyQueue(EnlQueueHandle, RX); +} + +void +NetvRxQueue::Start( + void +) +{ + auto link = NetvEnlMLink[m_adapter.EnlIndex].LinkHandle[0]; + auto port = &link->Ports[m_adapter.EnlPortIndex]; + auto queue = &port->RxQueue[0]; + + WDFVERIFY(queue->State == Stopped); + + queue->QueueNext = queue->QueueEnd = 0U; + + EnlIndicateQueueState(EnlQueueHandle, Started); +} + +void +NetvRxQueue::Stop( + void +) +{ + EnlIndicateQueueState(EnlQueueHandle, Stopped); +} + +_Use_decl_annotations_ +void +NetvRxQueue::Advance( + void +) +{ + auto fr = GetFragmentRing(); + NET_RING_PACKET_ITERATOR pi = NetRingGetAllPackets(m_rings); + NET_RING_FRAGMENT_ITERATOR fi = NetRingGetAllFragments(m_rings); + + // Ideally this would run in EvtQueueStart, but at that point the receive buffers are not + // attached to the fragment yet + if (! CheckedWakeFrame) + { + CheckForWakeFrame(this); + } + + // Move begin index forward for all fragments with Scratch == 1, thus returning them to the OS since we're done processing them. + for (; NetFragmentIteratorHasAny(&fi) && NetPacketIteratorHasAny(&pi); NetPacketIteratorAdvance(&pi), NetFragmentIteratorAdvance(&fi)) + { + NET_FRAGMENT const * fragment = NetFragmentIteratorGetFragment(&fi); + if (! fragment->Scratch) + { + break; + } + } + + NetFragmentIteratorSet(&fi); + NetPacketIteratorSet(&pi); + EnlRingDoorBell(EnlQueueHandle, fr->EndIndex); +} + +_Use_decl_annotations_ +void +NetvRxQueue::Cancel( + void +) +{ + CancelRxPackets(m_rings); +} + +_Use_decl_annotations_ +void +NetvRxQueue::SetNotify( + bool NotificationEnabled +) +{ + EnlArmInterrupt(EnlQueueHandle, NotificationEnabled); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/rxqueue.h b/network/netadaptercx/netvadapterlibrary/code/rxqueue.h new file mode 100644 index 00000000..cf208def --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/rxqueue.h @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved +#pragma once +#include "queue.h" + +class NetvRxQueue final + : public NetvQueue +{ + +public: + + NetvRxQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter + ); + + void + Destroy( + void + ); + + void + Start( + void + ); + + void + Stop( + void + ); + + void + Advance( + void + ); + + void + Cancel( + void + ); + + void + SetNotify( + bool Enable + ); + + ENLP_QUEUE * EnlQueueHandle; + + NET_EXTENSION VirtualAddressExtension; + NET_EXTENSION UdpRscExtension; + NET_EXTENSION RxXSumExtension; + NET_EXTENSION NetMemoryExtension; + NET_EXTENSION NetMemoryReturnContextExtensionIn; + + bool CheckedWakeFrame = false; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvRxQueue, NetvRxQueueGetContext); diff --git a/network/netadaptercx/netvadapterlibrary/code/trace.h b/network/netadaptercx/netvadapterlibrary/code/trace.h new file mode 100644 index 00000000..dc2e28e4 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/trace.h @@ -0,0 +1,96 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#pragma once + +#include <initguid.h> + +// 5EC34F87-7705-4B5B-B5F6-1F3E4665A31E +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + NetvadapterTraceGuid, \ + (5EC34F87,7705,4B5B,B5F6,1F3E4665A31E), \ + WPP_DEFINE_BIT(FLAG_DRIVER) \ + ) + +#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) + +// begin_wpp config +// USEPREFIX (LogInformation, "%!FUNC! ->"); +// LogVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...); +// end_wpp + +// begin_wpp config +// USEPREFIX (LogInformation, "%!FUNC! ->"); +// LogWarning{LEVEL=TRACE_LEVEL_WARNING}(FLAGS, MSG, ...); +// end_wpp + +// begin_wpp config +// USEPREFIX (LogInformation, "%!FUNC! ->"); +// LogError{LEVEL=TRACE_LEVEL_ERROR}(FLAGS, MSG, ...); +// end_wpp + +// begin_wpp config +// USEPREFIX (LogInformation, "%!FUNC! ->"); +// LogInformation{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS, MSG, ...); +// end_wpp + +// +// WPP orders static parameters before dynamic parameters. To support the Trace function +// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to +// reorder the arguments to what the .tpl configuration file expects. +// +#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) \ + WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags) + +#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) \ + WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags) + +// begin_wpp config +// USEPREFIX (RETURN_IF_NOT_STATUS_SUCCESS, "%!STATUS! %!FUNC! ->%!s!", nt__wpp, #NTSTATUS); +// FUNC RETURN_IF_NOT_STATUS_SUCCESS{FLAG=FLAG_DRIVER,LEVEL=TRACE_LEVEL_ERROR}(NTSTATUS); +// end_wpp + +#define WPP_FLAG_LEVEL_NTSTATUS_PRE(flag, level, ntstatus) do { NTSTATUS nt__wpp = (ntstatus); if (STATUS_SUCCESS != nt__wpp) { +#define WPP_FLAG_LEVEL_NTSTATUS_POST(flag, level, ntstatus); return nt__wpp; } } while (0) +#define WPP_RECORDER_FLAG_LEVEL_NTSTATUS_FILTER(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, flag) +#define WPP_RECORDER_FLAG_LEVEL_NTSTATUS_ARGS(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, flag) + +// begin_wpp config +// USEPREFIX (RETURN_NTSTATUS_IF, "%!STATUS! %!FUNC! ->%!s!", nt__wpp, #CONDITION); +// FUNC RETURN_NTSTATUS_IF{FLAG=FLAG_DRIVER,LEVEL=TRACE_LEVEL_ERROR}(NTSTATUS, CONDITION); +// end_wpp + +#define WPP_FLAG_LEVEL_NTSTATUS_CONDITION_PRE(flag, level, ntstatus, condition) if (condition) { NTSTATUS nt__wpp = (ntstatus); +#define WPP_FLAG_LEVEL_NTSTATUS_CONDITION_POST(flag, level, ntstatus, condition); return nt__wpp; } +#define WPP_RECORDER_FLAG_LEVEL_NTSTATUS_CONDITION_FILTER(flag, level, ntstatus, condition) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, flag) +#define WPP_RECORDER_FLAG_LEVEL_NTSTATUS_CONDITION_ARGS(flag, level, ntstatus, condition) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, flag) + +// begin_wpp config +// USEPREFIX (RETURN_FAILED_NTSTATUS_MSG, "%!STATUS! %!FUNC! ->", nt__wpp); +// FUNC RETURN_FAILED_NTSTATUS_MSG{FLAG=FLAG_DRIVER,FAILEDLEVEL=TRACE_LEVEL_ERROR}(NTSTATUS, MSG, ...); +// end_wpp + +#define WPP_FLAG_FAILEDLEVEL_NTSTATUS_PRE(flag, level, ntstatus); do { NTSTATUS nt__wpp = (ntstatus); +#define WPP_FLAG_FAILEDLEVEL_NTSTATUS_POST(flag, level, ntstatus); return nt__wpp; } while (0) +#define WPP_RECORDER_FLAG_FAILEDLEVEL_NTSTATUS_FILTER(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, flag) +#define WPP_RECORDER_FLAG_FAILEDLEVEL_NTSTATUS_ARGS(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, flag) + +// begin_wpp config +// USEPREFIX (RETURN_STATUS_SUCCESS, "%!STATUS! %!FUNC!", STATUS_SUCCESS); +// FUNC RETURN_STATUS_SUCCESS{FLAG=FLAG_DRIVER,SUCCESSLEVEL=TRACE_LEVEL_INFORMATION,NTSTATUS=STATUS_SUCCESS}(); +// end_wpp + +#define WPP_FLAG_SUCCESSLEVEL_NTSTATUS_POST(flag, level, ntstatus); return (ntstatus); +#define WPP_RECORDER_FLAG_SUCCESSLEVEL_NTSTATUS_FILTER(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, flag) +#define WPP_RECORDER_FLAG_SUCCESSLEVEL_NTSTATUS_ARGS(flag, level, ntstatus) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, flag) + diff --git a/network/netadaptercx/netvadapterlibrary/code/txqueue.cpp b/network/netadaptercx/netvadapterlibrary/code/txqueue.cpp new file mode 100644 index 00000000..b67692b5 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/txqueue.cpp @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "pch.hpp" +#include "netvadapter.h" +#include "txqueue.h" + +NetvTxQueue::NetvTxQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter +) noexcept + : NetvQueue{Handle, Adapter, NetTxQueueGetRingCollection(Handle)} +{ + NET_EXTENSION_QUERY extension; + NET_EXTENSION_QUERY_INIT( + &extension, + NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME, + NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1, + NetExtensionTypeFragment); + + NetTxQueueGetExtension(m_handle, &extension, &VirtualAddressExtension); + + NET_EXTENSION_QUERY_INIT( + &extension, + NET_PACKET_EXTENSION_GSO_NAME, + NET_PACKET_EXTENSION_GSO_VERSION_1, + NetExtensionTypePacket); + + NetTxQueueGetExtension(m_handle, &extension, &UsoExtension); + + EnlQueueHandle = EnlCreateQueue(Handle, TX); +} + +_Use_decl_annotations_ +void +NetvTxQueue::Destroy( + void +) +{ + EnlDestroyQueue(EnlQueueHandle, TX); +} + +void +NetvTxQueue::Start( + void +) +{ + auto link = NetvEnlMLink[m_adapter.EnlIndex].LinkHandle[0]; + auto port = &link->Ports[m_adapter.EnlPortIndex]; + auto queue = &port->TxQueue[0]; + + NT_ASSERT(queue->State == Stopped); + + queue->QueueNext = queue->QueueEnd = 0U; + + EnlIndicateQueueState(EnlQueueHandle, Started); +} + +void +NetvTxQueue::Stop( + void +) +{ + EnlIndicateQueueState(EnlQueueHandle, Stopped); +} + +_Use_decl_annotations_ +void +NetvTxQueue::Advance( + void +) +{ + auto pr = GetPacketRing(); + auto pi = NetRingGetAllPackets(m_rings); + + // drain Tx packets + for (; NetPacketIteratorHasAny(&pi); NetPacketIteratorAdvance(&pi)) + { + auto packet = NetPacketIteratorGetPacket(&pi); + if (! packet->Scratch) + { + break; + } + + auto fi = NetPacketIteratorGetFragments(&pi); + for (; NetFragmentIteratorHasAny(&fi); NetFragmentIteratorAdvance(&fi)) + { + continue; + } + + m_rings->Rings[NetRingTypeFragment]->BeginIndex = + NetFragmentIteratorGetIndex(&fi); + } + + NetPacketIteratorSet(&pi); + + // post Tx packets + EnlRingDoorBell(EnlQueueHandle, pr->EndIndex); +} + +_Use_decl_annotations_ +void +NetvTxQueue::Cancel( + void +) +{ + auto ringBuffer = GetPacketRing(); + + EnlRingDoorBell(EnlQueueHandle, ringBuffer->EndIndex); +} + +_Use_decl_annotations_ +void +NetvTxQueue::SetNotify( + bool NotificationEnabled +) +{ + EnlArmInterrupt(EnlQueueHandle, NotificationEnabled); +} diff --git a/network/netadaptercx/netvadapterlibrary/code/txqueue.h b/network/netadaptercx/netvadapterlibrary/code/txqueue.h new file mode 100644 index 00000000..425a38e9 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/code/txqueue.h @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved + +#include "queue.h" + +class NetvTxQueue final + : public NetvQueue +{ + +public: + + NetvTxQueue( + NETPACKETQUEUE Handle, + NetvAdapter & Adapter + ) noexcept; + + void + Destroy( + void + ); + + void + Start( + void + ); + + void + Stop( + void + ); + + void + Advance( + void + ); + + void + Cancel( + void + ); + + void + SetNotify( + bool Enable + ); + + ENLP_QUEUE * EnlQueueHandle; + NET_EXTENSION VirtualAddressExtension; + NET_EXTENSION UsoExtension; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NetvTxQueue, NetvTxQueueGetContext); diff --git a/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.filters b/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.filters new file mode 100644 index 00000000..1b227cbb --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.filters @@ -0,0 +1,26 @@ +<?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="KMDFDriver1.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.vcxproj b/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.vcxproj new file mode 100644 index 00000000..8167e906 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/ethernet_km/netvadapterlibrarykm.vcxproj @@ -0,0 +1,189 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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 /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\code\configuration.h" /> + <ClInclude Include="..\code\enl.h" /> + <ClInclude Include="..\code\enlthreads.h" /> + <ClInclude Include="..\code\memory.h" /> + <ClInclude Include="..\code\pch.hpp" /> + <ClInclude Include="..\code\queue.h" /> + <ClInclude Include="..\code\rxqueue.h" /> + <ClInclude Include="..\code\trace.h" /> + <ClInclude Include="..\code\txqueue.h" /> + <ClInclude Include="..\Interface\netvadapter.h" /> + <ClInclude Include="..\netvInterface.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\code\adapter.cpp" /> + <ClCompile Include="..\code\configuration.cpp" /> + <ClCompile Include="..\code\enl.cpp" /> + <ClCompile Include="..\code\enlthreads.cpp" /> + <ClCompile Include="..\code\memory.cpp" /> + <ClCompile Include="..\code\queue.cpp" /> + <ClCompile Include="..\code\rxqueue.cpp" /> + <ClCompile Include="..\code\txqueue.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.filters b/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.filters new file mode 100644 index 00000000..1b227cbb --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.filters @@ -0,0 +1,26 @@ +<?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="KMDFDriver1.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.vcxproj b/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.vcxproj new file mode 100644 index 00000000..0ed7a371 --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/ethernet_um/netvadapterlibraryum.vcxproj @@ -0,0 +1,185 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{612F33AD-430C-4FE7-8000-35E15A5EB757}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>KMDF_Driver1</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>33</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>33</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>33</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>33</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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 /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\code\configuration.h" /> + <ClInclude Include="..\code\enl.h" /> + <ClInclude Include="..\code\enlthreads.h" /> + <ClInclude Include="..\code\memory.h" /> + <ClInclude Include="..\code\pch.hpp" /> + <ClInclude Include="..\code\queue.h" /> + <ClInclude Include="..\code\rxqueue.h" /> + <ClInclude Include="..\code\trace.h" /> + <ClInclude Include="..\code\txqueue.h" /> + <ClInclude Include="..\Interface\netvadapter.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\code\adapter.cpp" /> + <ClCompile Include="..\code\configuration.cpp" /> + <ClCompile Include="..\code\enl.cpp" /> + <ClCompile Include="..\code\enlthreads.cpp" /> + <ClCompile Include="..\code\memory.cpp" /> + <ClCompile Include="..\code\queue.cpp" /> + <ClCompile Include="..\code\rxqueue.cpp" /> + <ClCompile Include="..\code\txqueue.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.filters b/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.filters new file mode 100644 index 00000000..1b227cbb --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.filters @@ -0,0 +1,26 @@ +<?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="KMDFDriver1.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.vcxproj b/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.vcxproj new file mode 100644 index 00000000..f674c91a --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/wifi_km/netvadapterlibrarykm.vcxproj @@ -0,0 +1,189 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>6</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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 /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <WppRecorderEnabled>true</WppRecorderEnabled> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\code\configuration.h" /> + <ClInclude Include="..\code\enl.h" /> + <ClInclude Include="..\code\enlthreads.h" /> + <ClInclude Include="..\code\memory.h" /> + <ClInclude Include="..\code\pch.hpp" /> + <ClInclude Include="..\code\queue.h" /> + <ClInclude Include="..\code\rxqueue.h" /> + <ClInclude Include="..\code\trace.h" /> + <ClInclude Include="..\code\txqueue.h" /> + <ClInclude Include="..\Interface\netvadapter.h" /> + <ClInclude Include="..\netvInterface.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\code\adapter.cpp" /> + <ClCompile Include="..\code\configuration.cpp" /> + <ClCompile Include="..\code\enl.cpp" /> + <ClCompile Include="..\code\enlthreads.cpp" /> + <ClCompile Include="..\code\memory.cpp" /> + <ClCompile Include="..\code\queue.cpp" /> + <ClCompile Include="..\code\rxqueue.cpp" /> + <ClCompile Include="..\code\txqueue.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.filters b/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.filters new file mode 100644 index 00000000..1b227cbb --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.filters @@ -0,0 +1,26 @@ +<?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="KMDFDriver1.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.vcxproj b/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.vcxproj new file mode 100644 index 00000000..e7c260cf --- /dev/null +++ b/network/netadaptercx/netvadapterlibrary/wifi_um/netvadapterlibraryum.vcxproj @@ -0,0 +1,189 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{612F33AD-430C-4FE7-8000-35E15A5EB757}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>KMDF_Driver1</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>35</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>6</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>35</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>35</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>StaticLibrary</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>35</UMDF_VERSION_MINOR> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_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 /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <IncludePath>$(MSBuildProjectDirectory)\..\Interface;$(MSBuildProjectDirectory)\..\code\rtl;$(IncludePath)</IncludePath> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + </ClCompile> + <ClCompile> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\code\trace.h</WppScanConfigurationData> + <AdditionalIncludeDirectories>..\..\..\..\wil\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\code\configuration.h" /> + <ClInclude Include="..\code\enl.h" /> + <ClInclude Include="..\code\enlthreads.h" /> + <ClInclude Include="..\code\memory.h" /> + <ClInclude Include="..\code\pch.hpp" /> + <ClInclude Include="..\code\queue.h" /> + <ClInclude Include="..\code\rxqueue.h" /> + <ClInclude Include="..\code\trace.h" /> + <ClInclude Include="..\code\txqueue.h" /> + <ClInclude Include="..\Interface\netvadapter.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\code\adapter.cpp" /> + <ClCompile Include="..\code\configuration.cpp" /> + <ClCompile Include="..\code\enl.cpp" /> + <ClCompile Include="..\code\enlthreads.cpp" /> + <ClCompile Include="..\code\memory.cpp" /> + <ClCompile Include="..\code\queue.cpp" /> + <ClCompile Include="..\code\rxqueue.cpp" /> + <ClCompile Include="..\code\txqueue.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_AdvancedPacketInjectionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_AdvancedPacketInjectionCallouts.cpp index 1df1f7b5..b71c77e0 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_AdvancedPacketInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_AdvancedPacketInjectionCallouts.cpp @@ -99,7 +99,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_AdvancedPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_AdvancedPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if DBG diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicActionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicActionCallouts.cpp index 375dab93..69773e8a 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicActionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicActionCallouts.cpp @@ -52,7 +52,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_BasicActionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_BasicActionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PerformBasicAction" diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketInjectionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketInjectionCallouts.cpp index 2409a64d..641cb8be 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketInjectionCallouts.cpp @@ -103,7 +103,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_BasicPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_BasicPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if DBG diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketModificationCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketModificationCallouts.cpp index d6acb876..1a31999f 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketModificationCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketModificationCallouts.cpp @@ -106,7 +106,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_BasicPacketModificationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_BasicPacketModificationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN8) diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicStreamInjectionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicStreamInjectionCallouts.cpp index 493fdace..7624c0f6 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_BasicStreamInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_BasicStreamInjectionCallouts.cpp @@ -54,7 +54,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_BasicStreamInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_BasicStreamInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PerformBasicPacketInjectionAtOutboundTransport" diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_FastPacketInjectionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_FastPacketInjectionCallouts.cpp index b7bf9fc9..0e99b61e 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_FastPacketInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_FastPacketInjectionCallouts.cpp @@ -46,7 +46,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_FastPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_FastPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN7) diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_FastStreamInjectionCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_FastStreamInjectionCallouts.cpp index 07822e88..a10b0d8a 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_FastStreamInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_FastStreamInjectionCallouts.cpp @@ -42,7 +42,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_FastStreamInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_FastStreamInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN7) diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_FlowAssociationCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_FlowAssociationCallouts.cpp index 179a7ac0..f1c7f905 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_FlowAssociationCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_FlowAssociationCallouts.cpp @@ -39,7 +39,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_FlowAssociationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_FlowAssociationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ NTSTATUS PerformFlowAssociation(_In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _In_ const PC_FLOW_ASSOCIATION_DATA* pFlowAssociationData) diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp index f4f23eba..b3f3ba15 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp @@ -47,7 +47,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_PendAuthorizationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_PendAuthorizationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PrvCloneAuthorizedNBLAndInject" diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp index 315dde6c..d8d88721 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_PendEndpointClosureCallouts.cpp @@ -44,7 +44,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_PendEndpointClosureCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_PendEndpointClosureCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN7) diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_ProxyCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_ProxyCallouts.cpp index d6b2b4d4..f0cc853c 100644 --- a/network/trans/WFPSampler/sys/ClassifyFunctions_ProxyCallouts.cpp +++ b/network/trans/WFPSampler/sys/ClassifyFunctions_ProxyCallouts.cpp @@ -58,7 +58,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "ClassifyFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "ClassifyFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PerformProxyInjectionAtInboundNetwork" diff --git a/network/trans/WFPSampler/sys/CompletionFunctions_AdvancedPacketInjectionCallouts.cpp b/network/trans/WFPSampler/sys/CompletionFunctions_AdvancedPacketInjectionCallouts.cpp index 7348cb8d..cccaf200 100644 --- a/network/trans/WFPSampler/sys/CompletionFunctions_AdvancedPacketInjectionCallouts.cpp +++ b/network/trans/WFPSampler/sys/CompletionFunctions_AdvancedPacketInjectionCallouts.cpp @@ -52,7 +52,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "CompletionFunctions_AdvancedPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "CompletionFunctions_AdvancedPacketInjectionCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if DBG diff --git a/network/trans/WFPSampler/sys/CompletionFunctions_BasicPacketModificationCallouts.cpp b/network/trans/WFPSampler/sys/CompletionFunctions_BasicPacketModificationCallouts.cpp index ef51c44b..cd240d4e 100644 --- a/network/trans/WFPSampler/sys/CompletionFunctions_BasicPacketModificationCallouts.cpp +++ b/network/trans/WFPSampler/sys/CompletionFunctions_BasicPacketModificationCallouts.cpp @@ -54,7 +54,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "CompletionFunctions_BasicPacketModificationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "CompletionFunctions_BasicPacketModificationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="BasicPacketModificationCompletionDataDestroy" diff --git a/network/trans/WFPSampler/sys/CompletionFunctions_PendAuthorizationCallouts.cpp b/network/trans/WFPSampler/sys/CompletionFunctions_PendAuthorizationCallouts.cpp index e48a9ef8..7dd07b78 100644 --- a/network/trans/WFPSampler/sys/CompletionFunctions_PendAuthorizationCallouts.cpp +++ b/network/trans/WFPSampler/sys/CompletionFunctions_PendAuthorizationCallouts.cpp @@ -53,7 +53,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "CompletionFunctions_PendAuthorizationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "CompletionFunctions_PendAuthorizationCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PendAuthorizationCompletionDataDestroy" diff --git a/network/trans/WFPSampler/sys/CompletionFunctions_ProxyCallouts.cpp b/network/trans/WFPSampler/sys/CompletionFunctions_ProxyCallouts.cpp index ec47380e..d7527901 100644 --- a/network/trans/WFPSampler/sys/CompletionFunctions_ProxyCallouts.cpp +++ b/network/trans/WFPSampler/sys/CompletionFunctions_ProxyCallouts.cpp @@ -53,7 +53,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "CompletionFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "CompletionFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="ProxyCompletionDataDestroy" diff --git a/network/trans/WFPSampler/sys/Framework_Events.cpp b/network/trans/WFPSampler/sys/Framework_Events.cpp index baf59cc8..8f8001cc 100644 --- a/network/trans/WFPSampler/sys/Framework_Events.cpp +++ b/network/trans/WFPSampler/sys/Framework_Events.cpp @@ -20,7 +20,7 @@ #include "Framework_WFPSamplerCalloutDriver.h" /// . #include "Framework_Include.h" /// . -#include "Framework_Events.tmh" /// $(OBJ_PATH)\$(O)\ +#include "Framework_Events.tmh" /// $(OBJ_PATH)\$(O)\ /** @framework_function="EventDriverUnload" diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_AdvancedCallouts.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_AdvancedCallouts.cpp index 18c93824..badbe806 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_AdvancedCallouts.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_AdvancedCallouts.cpp @@ -32,7 +32,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_AdvancedCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_AdvancedCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PrvAdvancedNotificationWorkItemRoutine" diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_BasicCallouts.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_BasicCallouts.cpp index 6b86daaf..3893d7d1 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_BasicCallouts.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_BasicCallouts.cpp @@ -34,7 +34,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_BasicCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_BasicCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PrvBasicNotificationWorkItemRoutine" diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_FastCallouts.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_FastCallouts.cpp index 92011dfc..e7addba7 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_FastCallouts.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_FastCallouts.cpp @@ -34,7 +34,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_FastCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_FastCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PrvFastNotificationWorkItemRoutine" diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_FlowDelete.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_FlowDelete.cpp index bf1506ce..ab320f62 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_FlowDelete.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_FlowDelete.cpp @@ -32,7 +32,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_FlowDelete.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_FlowDelete.tmh" /// $(OBJ_PATH)\$(O)\ _IRQL_requires_min_(PASSIVE_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL) diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_PendCallouts.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_PendCallouts.cpp index e8b1fd63..1cc2913f 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_PendCallouts.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_PendCallouts.cpp @@ -34,7 +34,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_PendCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_PendCallouts.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_function="PrvPendNotificationWorkItemRoutine" diff --git a/network/trans/WFPSampler/sys/NotifyFunctions_ProxyCallouts.cpp b/network/trans/WFPSampler/sys/NotifyFunctions_ProxyCallouts.cpp index 5102b78d..b11d8569 100644 --- a/network/trans/WFPSampler/sys/NotifyFunctions_ProxyCallouts.cpp +++ b/network/trans/WFPSampler/sys/NotifyFunctions_ProxyCallouts.cpp @@ -35,7 +35,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "NotifyFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ +#include "NotifyFunctions_ProxyCallouts.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN7) diff --git a/network/trans/WFPSampler/sys/SubscriptionFunctions_BFEState.cpp b/network/trans/WFPSampler/sys/SubscriptionFunctions_BFEState.cpp index 8c141627..52e0b36b 100644 --- a/network/trans/WFPSampler/sys/SubscriptionFunctions_BFEState.cpp +++ b/network/trans/WFPSampler/sys/SubscriptionFunctions_BFEState.cpp @@ -34,7 +34,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "Framework_WFPSamplerCalloutDriver.h" /// . -#include "SubscriptionFunctions_BFEState.tmh" /// $(OBJ_PATH)\$(O)\ +#include "SubscriptionFunctions_BFEState.tmh" /// $(OBJ_PATH)\$(O)\ /** @notify_function="SubscriptionBFEStateChangeCallback" diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_FlowContext.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_FlowContext.cpp index a21dcf8a..e53a5e33 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_FlowContext.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_FlowContext.cpp @@ -42,7 +42,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_FlowContext.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_FlowContext.tmh" /// $(OBJ_PATH)\$(O)\ _IRQL_requires_min_(PASSIVE_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL) diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_FwpObjects.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_FwpObjects.cpp index 77324785..0b753a57 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_FwpObjects.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_FwpObjects.cpp @@ -74,7 +74,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_FwpObjects.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_FwpObjects.tmh" /// $(OBJ_PATH)\$(O)\ HANDLE g_EngineHandle = 0; HANDLE g_pIPv4InboundMACInjectionHandles[2] = {0}; diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp index 3e400890..f5bb66e3 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp @@ -84,7 +84,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_Headers.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_Headers.tmh" /// $(OBJ_PATH)\$(O)\ /** @private_kernel_helper_function="PrvKrnlHlprCopyBufferToMDL" diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_NetBuffer.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_NetBuffer.cpp index 2d6bd3c9..4338d787 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_NetBuffer.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_NetBuffer.cpp @@ -49,7 +49,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_NetBuffer.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_NetBuffer.tmh" /// $(OBJ_PATH)\$(O)\ /** diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_PendData.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_PendData.cpp index bc2528a0..d8db09ee 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_PendData.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_PendData.cpp @@ -49,7 +49,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_PendData.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_PendData.tmh" /// $(OBJ_PATH)\$(O)\ /** @kernel_helper_function="KrnlHlprPendDataPurge" diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_RedirectData.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_RedirectData.cpp index 22f08c60..92cca4ba 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_RedirectData.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_RedirectData.cpp @@ -48,7 +48,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_RedirectData.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_RedirectData.tmh" /// $(OBJ_PATH)\$(O)\ #if(NTDDI_VERSION >= NTDDI_WIN7) diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp index 3a5f7696..7e4f8c16 100644 --- a/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp +++ b/network/trans/WFPSampler/syslib/HelperFunctions_WorkItems.cpp @@ -54,7 +54,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// #include "HelperFunctions_Include.h" /// . -#include "HelperFunctions_WorkItems.tmh" /// $(OBJ_PATH)\$(O)\ +#include "HelperFunctions_WorkItems.tmh" /// $(OBJ_PATH)\$(O)\ /** @kernel_helper_function="KrnlHlprWorkItemDataPurge" diff --git a/network/wlan/wificx/OEM/OemDeviceService.vcxproj b/network/wlan/wificx/OEM/OemDeviceService.vcxproj new file mode 100644 index 00000000..c48f5bb8 --- /dev/null +++ b/network/wlan/wificx/OEM/OemDeviceService.vcxproj @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <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|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}</ProjectGuid> + <RootNamespace>OemDeviceService</RootNamespace> + <ConfigurationType>Application</ConfigurationType> + <CharacterSet>Unicode</CharacterSet> + <ProjectName>OemDeviceServiceApplication</ProjectName> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ItemDefinitionGroup> + <ClCompile> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>wlanapi.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="OemDeviceServiceApp.cpp" /> + </ItemGroup> + <ItemGroup> + <None Include="README.md" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/wlan/wificx/OEM/OemDeviceServiceApp.cpp b/network/wlan/wificx/OEM/OemDeviceServiceApp.cpp new file mode 100644 index 00000000..74c0e3d3 --- /dev/null +++ b/network/wlan/wificx/OEM/OemDeviceServiceApp.cpp @@ -0,0 +1,158 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// OEM sample: enumerates supported device services, then sends "Hello, My Driver" +// to the WiFiCx sample driver via WlanDeviceServiceCommand and prints the +// driver's "Nice to meet you, My OEM". + +#define NOMINMAX // use std::min/std::max instead of the windows.h min/max macros +#include <windows.h> +#include <wlanapi.h> +#include <objbase.h> // StringFromGUID2 +#include <algorithm> // std::min +#include <cstdio> + +#pragma comment(lib, "wlanapi.lib") +#pragma comment(lib, "ole32.lib") // StringFromGUID2 + +// WlanGetSupportedDeviceServices, WlanDeviceServiceCommand and +// WLAN_DEVICE_SERVICE_GUID_LIST are all declared by wlanapi.h. + +// This GUID/opcode pair MUST match the driver (drivercode\SharedTypes.h). +// {2d6f9a14-3a1d-4f0a-9b7e-1c2e3a4b5c6d} +static const GUID GUID_OEM_SAMPLE_DEVICE_SERVICE = +{ 0x2d6f9a14, 0x3a1d, 0x4f0a, { 0x9b, 0x7e, 0x1c, 0x2e, 0x3a, 0x4b, 0x5c, 0x6d } }; + +#define OEM_DEVICE_SERVICE_OPCODE_HELLO 0x00000001 +#define OEM_DEVICE_SERVICE_REQUEST_STRING "Hello, My Driver" + +static void PrintGuid(const GUID& g) +{ + wchar_t buf[64] = { 0 }; + StringFromGUID2(g, buf, ARRAYSIZE(buf)); + wprintf(L"%s", buf); +} + +// Enumerate the device services the driver advertises (via WDI_GET_SUPPORTED_DEVICE_SERVICES). +static bool QuerySupportedServices(HANDLE hClient, const GUID& interfaceGuid) +{ + PWLAN_DEVICE_SERVICE_GUID_LIST pList = nullptr; + DWORD result = WlanGetSupportedDeviceServices(hClient, &interfaceGuid, &pList); + if (result != ERROR_SUCCESS || pList == nullptr) + { + printf("WlanGetSupportedDeviceServices failed with error %u\n", result); + return false; + } + + bool found = false; + printf("Supported device services: %u\n", pList->dwNumberOfItems); + for (DWORD i = 0; i < pList->dwNumberOfItems; i++) + { + printf(" [%u] ", i); + PrintGuid(pList->DeviceService[i]); + if (IsEqualGUID(pList->DeviceService[i], GUID_OEM_SAMPLE_DEVICE_SERVICE)) + { + found = true; + printf(" <-- OEM sample service"); + } + printf("\n"); + } + + WlanFreeMemory(pList); + return found; +} + +static void SendHelloToInterface(HANDLE hClient, const GUID& interfaceGuid) +{ + char inBuffer[] = OEM_DEVICE_SERVICE_REQUEST_STRING; // includes null terminator + DWORD inBufferSize = static_cast<DWORD>(sizeof(inBuffer)); + + BYTE outBuffer[256] = { 0 }; + DWORD outBufferSize = static_cast<DWORD>(sizeof(outBuffer)); + DWORD bytesReturned = 0; + + printf("Sending device service command: \"%s\"\n", inBuffer); + + DWORD result = WlanDeviceServiceCommand( + hClient, + &interfaceGuid, + const_cast<LPGUID>(&GUID_OEM_SAMPLE_DEVICE_SERVICE), + OEM_DEVICE_SERVICE_OPCODE_HELLO, + inBufferSize, + inBuffer, + outBufferSize, + outBuffer, + &bytesReturned); + + if (result != ERROR_SUCCESS) + { + printf("WlanDeviceServiceCommand failed with error %u\n", result); + return; + } + + if (bytesReturned > 0) + { + outBuffer[std::min(bytesReturned, static_cast<DWORD>(sizeof(outBuffer) - 1))] = '\0'; + printf("Driver responded: \"%s\" (%u bytes)\n", reinterpret_cast<char*>(outBuffer), bytesReturned); + } + else + { + printf("Driver returned no data.\n"); + } +} + +int __cdecl main() +{ + HANDLE hClient = nullptr; + DWORD negotiatedVersion = 0; + PWLAN_INTERFACE_INFO_LIST pIfList = nullptr; + + // 1) WlanOpenHandle + DWORD result = WlanOpenHandle(WLAN_API_VERSION_2_0, nullptr, &negotiatedVersion, &hClient); + if (result != ERROR_SUCCESS) + { + printf("WlanOpenHandle failed with error %u\n", result); + return 1; + } + + // 2) WlanEnumInterfaces + result = WlanEnumInterfaces(hClient, nullptr, &pIfList); + if (result != ERROR_SUCCESS) + { + printf("WlanEnumInterfaces failed with error %u\n", result); + WlanCloseHandle(hClient, nullptr); + return 1; + } + + printf("Found %u WLAN interface(s).\n", pIfList->dwNumberOfItems); + + for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++) + { + const WLAN_INTERFACE_INFO& ifInfo = pIfList->InterfaceInfo[i]; + printf("\nInterface[%u]: %ws\n", i, ifInfo.strInterfaceDescription); + + // Enumerate supported device services first. + bool supported = QuerySupportedServices(hClient, ifInfo.InterfaceGuid); + + // 3) WlanDeviceServiceCommand (only if our service is advertised) + if (supported) + { + SendHelloToInterface(hClient, ifInfo.InterfaceGuid); + } + else + { + printf("OEM sample device service not advertised on this interface; skipping command.\n"); + } + } + + // 4) WlanFreeMemory(pIfList); + if (pIfList != nullptr) + { + WlanFreeMemory(pIfList); + pIfList = nullptr; + } + + // 5) WlanCloseHandle(hClient, nullptr); + WlanCloseHandle(hClient, nullptr); + + return 0; +} diff --git a/network/wlan/wificx/OEM/README.md b/network/wlan/wificx/OEM/README.md new file mode 100644 index 00000000..98419932 --- /dev/null +++ b/network/wlan/wificx/OEM/README.md @@ -0,0 +1,90 @@ +# OEM Device Service Sample (`OemDeviceServiceApplication`) + +A user-mode console application that demonstrates how an OEM/IHV utility communicates +with the WiFiCx sample driver through a **WLAN device service**. The app sends the +request string `"Hello, My Driver"` and prints the driver's reply +`"Nice to meet you, My OEM"`. + +## What it does + +The tool walks through the standard WLAN client flow: + +1. **`WlanOpenHandle`** — opens a client handle using `WLAN_API_VERSION_2_0`. +2. **`WlanEnumInterfaces`** — enumerates all WLAN interfaces on the machine. +3. **`WlanGetSupportedDeviceServices`** — for each interface, enumerates the device + service GUIDs the driver advertises and checks whether the OEM sample service + (`GUID_OEM_SAMPLE_DEVICE_SERVICE`) is present. +4. **`WlanDeviceServiceCommand`** — when the service is advertised, sends the + `OEM_DEVICE_SERVICE_OPCODE_HELLO` opcode with the request payload and prints the + bytes returned by the driver. +5. **`WlanFreeMemory` / `WlanCloseHandle`** — releases the interface list and the + client handle. + +If the OEM sample device service is not advertised on an interface, the command is +skipped for that interface. + +## Device service contract + +These values **must stay in sync** with the driver-side definitions in +[`drivercode/SharedTypes.h`](../drivercode/SharedTypes.h): + +| Item | Value | +| --- | --- | +| Service GUID | `{2d6f9a14-3a1d-4f0a-9b7e-1c2e3a4b5c6d}` (`GUID_OEM_SAMPLE_DEVICE_SERVICE`) | +| Opcode | `0x00000001` (`OEM_DEVICE_SERVICE_OPCODE_HELLO`) | +| Request string | `"Hello, My Driver"` | +| Response string | `"Nice to meet you, My OEM"` | + +The driver advertises the service GUID via `WDI_GET_SUPPORTED_DEVICE_SERVICES`, so the +GUID must match on both sides for the exchange to succeed. + +## Source layout + +| File | Purpose | +| --- | --- | +| [`OemDeviceServiceApp.cpp`](OemDeviceServiceApp.cpp) | Application entry point and device service logic. | +| [`OemDeviceService.vcxproj`](OemDeviceService.vcxproj) | MSBuild project for the console app. | + +## Build + +The project (`OemDeviceService.vcxproj`) builds as a console **Application** using the +`WindowsApplicationForDrivers10.0` platform toolset. + +- **Configurations:** `Debug`, `Release` +- **Platforms:** `x64`, `ARM64` +- **Linked libraries:** `wlanapi.lib`, `ole32.lib` + +Build it from Visual Studio as part of the solution, or from the command line: + +```cmd +msbuild OEM\OemDeviceService.vcxproj /p:Configuration=Release /p:Platform=x64 +``` + +## Run + +Run the resulting executable from an elevated command prompt on a machine where the +WiFiCx sample driver is installed: + +```cmd +OemDeviceServiceApplication.exe +``` + +### Example output + +```text +Found 1 WLAN interface(s). + +Interface[0]: WiFiCx Sample Client Device +Supported device services: 1 + [0] {2D6F9A14-3A1D-4F0A-9B7E-1C2E3A4B5C6D} <-- OEM sample service +Sending device service command: "Hello, My Driver" +Driver responded: "Nice to meet you, My OEM" (25 bytes) +``` + +## Requirements + +- The WiFiCx sample driver must be installed and the adapter present. +- The driver must advertise `GUID_OEM_SAMPLE_DEVICE_SERVICE`; otherwise the app prints + that the service is not advertised and skips the command. +- WLAN API (`wlanapi.lib`) and COM (`ole32.lib` for `StringFromGUID2`) are available on + the host. diff --git a/network/wlan/wificx/README.md b/network/wlan/wificx/README.md new file mode 100644 index 00000000..fb4ca92a --- /dev/null +++ b/network/wlan/wificx/README.md @@ -0,0 +1,50 @@ +--- +page_type: sample +description: "Demonstrates how to use WIFICX for control flow and NetAdapterCx for data flow." +languages: +- cpp +products: +- windows +- windows-wdk +--- + +# WIFICX and NetAdapterCx Samples + +This sample illustrates how to leverage **WIFICX** for control flow and **NetAdapterCx** for data flow. It supports both **KMDF** and **UMDF(In Preview Stage)** drivers. + +## How to Build +1. Mount the EWDK ISO from a local drive (network share paths are not supported). +2. Run `LaunchBuildEnv.cmd`. +3. In the environment created in step 2, type `SetupVSEnv` and press **Enter**. +4. Navigate to the current folder and open the solution file, for example: + `X:\Windows-driver-samples\network\wlan\WIFICX\wificxsampleclient.sln` +5. Build the solution from the Visual Studio UI. + +## Interfaces and Abstraction +The sample interacts with three OS components: + +- **WDF** + `driver.cpp`, `device.cpp`, and `adapter.cpp` demonstrate proper registration for PnP and power event callbacks. WDF manages system PnP and power requests (e.g., power IRPs), so IHV drivers should follow the flow triggered through these callbacks. + +- **WDF Wi-Fi Class Extension (WIFICX)** + `wifixxxxx.cpp` files implement the **control path**, handling commands sent to Wi-Fi firmware (e.g., scan access points, connect, disconnect). + +- **WDF NetAdapter Class Extension (NetAdapterCx)** + `netvxxxx` files and classes implement the **data path**, managing network buffers and synchronizing with the control path for transfer start/stop operations. + +## Data Buffers from Firmware +The control path uses hardcoded data since this sample does not target real hardware. The data path uses **Emulated Network Link (ENL)**, which connects two virtual network adapters directly. Packets sent over one adapter are delivered to the other and vice versa. + +## Supported Scenarios +- [x] Scan access points and report BSS entries to the Windows UI. +- [x] Connect to an open access point from the Windows UI. +- [x] Disconnect from the connected access point. +- [x] Transfer data between two Wi-Fi device instances (e.g., ping and throughput test). + +## 🎥 Control & Data Path Demo Video +A walkthrough video demonstrating the Control & Data Path flow are available here: + +[▶ Watch Control Path Demo](video/ControlPath.mp4) + +[▶ Watch Data Path Demo](video/DataPath.mp4) + diff --git a/network/wlan/wificx/drivercode/SharedTypes.h b/network/wlan/wificx/drivercode/SharedTypes.h new file mode 100644 index 00000000..e454378b --- /dev/null +++ b/network/wlan/wificx/drivercode/SharedTypes.h @@ -0,0 +1,31 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +// +// SharedTypes.h +// Central header for global definitions, macros, and shared structures. +// +#include "precomp.h" +#include <initguid.h> // for GUID defination + +// ============================= +// GUIDs or Constants +// ============================= +// {bb67559a-06f6-4eb0-81e9-21fdc3b60efb} +DEFINE_GUID(GUID_WIFICX_SAMPLE_CLIENT_INTERFACE, 0xbb67559a, 0x06f6, 0x4eb0, 0x81, 0xe9, 0x21, 0xfd, 0xc3, 0xb6, 0x0e, 0xfb); +#define WIFI_DRIVER_DEFAULT_POOL_TAG 'shiW' // WIFI IHV Sample Driver + +// ============================= +// OEM Device Service contract +// ============================= +// This GUID/opcode pair MUST match the OEM user-mode app (OEM\OemDeviceService.cpp). +// {2d6f9a14-3a1d-4f0a-9b7e-1c2e3a4b5c6d} +DEFINE_GUID(GUID_OEM_SAMPLE_DEVICE_SERVICE, + 0x2d6f9a14, 0x3a1d, 0x4f0a, 0x9b, 0x7e, 0x1c, 0x2e, 0x3a, 0x4b, 0x5c, 0x6d); + +// Opcode understood by the driver for the "hello / nice to meet you" exchange. +#define OEM_DEVICE_SERVICE_OPCODE_HELLO 0x00000001 + +// Payload strings exchanged with the OEM app. +#define OEM_DEVICE_SERVICE_REQUEST_STRING "Hello, My Driver" +#define OEM_DEVICE_SERVICE_RESPONSE_STRING "Nice to meet you, My OEM"
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/adapter.cpp b/network/wlan/wificx/drivercode/adapter.cpp new file mode 100644 index 00000000..fd44c72b --- /dev/null +++ b/network/wlan/wificx/drivercode/adapter.cpp @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +#include "precomp.h" +#include "adapter.h" +#include "adapter.tmh" + +extern UCHAR NetvMacAddressBase[MAC_ADDR_LEN]; + +NetvAdapter* NetvAdapterGetContextFromWDFObject(NETADAPTER netAdapter) +{ + WifiNetvAdapter* wifiNetvAdapter = WifiNetvAdapterGetContext(netAdapter); + NetvAdapter* netvAdapter{ wifiNetvAdapter }; + return netvAdapter; +} + +WifiNetvAdapter::WifiNetvAdapter(NETADAPTER Handle, WDFDEVICE Device) : NetvAdapter(Handle, Device) +{ +} + +NTSTATUS WifiNetvAdapter::Initialize() +{ + if (WifiGetIhvDeviceContext(m_device)->netAdapters[WifiAdapterGetPortId(m_handle)] != WDF_NO_HANDLE) + { + return STATUS_SUCCESS; + } + return NetvAdapter::Initialize(); +} + +NTSTATUS WifiNetvAdapter::AdapterStart() +{ + TraceEntry(); + + NTSTATUS status = STATUS_SUCCESS; + + NET_ADAPTER_WAKE_MEDIA_CHANGE_CAPABILITIES wakeMediaChangeCapabilities; + NET_ADAPTER_WAKE_MEDIA_CHANGE_CAPABILITIES_INIT(&wakeMediaChangeCapabilities); + + wakeMediaChangeCapabilities.MediaConnect = TRUE; + wakeMediaChangeCapabilities.MediaDisconnect = TRUE; + + NetAdapterWakeSetMediaChangeCapabilities(m_handle, &wakeMediaChangeCapabilities); + + WIFI_ADAPTER_WAKE_CAPABILITIES wakeCap{}; + WIFI_ADAPTER_WAKE_CAPABILITIES_INIT(&wakeCap); + if (WIFI_IS_FIELD_AVAILABLE(WIFI_ADAPTER_WAKE_CAPABILITIES, ClientDriverDiagnostic)) + { + wakeCap.ClientDriverDiagnostic = true; + } + WifiAdapterSetWakeCapabilities(m_handle, &wakeCap); + + status = NetvAdapter::ConfigureDataCapabilities(); + if (!NT_SUCCESS(status)) + { + WFCError("%!FUNC!: NetvAdapter::ConfigureDataCapabilities failed with %!STATUS!", status); + return status; + } + + status = NetAdapterStart(m_handle); + if (!NT_SUCCESS(status)) + { + WFCError("%!FUNC!: NetAdapterStart failed with %!STATUS!", status); + return status; + } + + ASSERT(STATUS_SUCCESS == status); + TraceExit(status); + + return status; +} + +NTSTATUS WifiNetvAdapter::CreateRxQueue(NETRXQUEUE_INIT* NetRxQueueInit) +{ + return NetvAdapter::CreateRxQueue(NetRxQueueInit); +} + +NTSTATUS WifiNetvAdapter::CreateTxQueue(NETTXQUEUE_INIT* NetTxQueueInit) +{ + return NetvAdapter::CreateTxQueue(NetTxQueueInit); +} + +void WifiNetvAdapter::Destroy(void) +{ + return NetvAdapter::Destroy(); +}
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/adapter.h b/network/wlan/wificx/drivercode/adapter.h new file mode 100644 index 00000000..0b7aa093 --- /dev/null +++ b/network/wlan/wificx/drivercode/adapter.h @@ -0,0 +1,42 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once +#include "device.h" +#include "netvadapter.h" + +// for STA TX DEMUX +#define MaxNumOfPeers 1 + +// Context for each "Wdi Port"[NetAdapter] instance. +// Each NetAdapter instance corresponds to an IP interface +typedef struct _WIFI_IHV_NETADAPTER_CONTEXT +{ + PWIFI_IHV_DEVICE_CONTEXT WifiDeviceContext; // Wdf Ihv device context + NETADAPTER NetAdapter; // NetAdapter object +} WIFI_IHV_NETADAPTER_CONTEXT, * PWIFI_IHV_NETADAPTER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WIFI_IHV_NETADAPTER_CONTEXT, WifiGetIhvNetAdapterContext); + +class WifiNetvAdapter : public NetvAdapter +{ +public: + WifiNetvAdapter(NETADAPTER Handle, WDFDEVICE Device); + + NTSTATUS + Initialize(); + + NTSTATUS + AdapterStart(); + + NTSTATUS + CreateRxQueue(NETRXQUEUE_INIT* NetRxQueueInit); + + NTSTATUS + CreateTxQueue(NETTXQUEUE_INIT* NetTxQueueInit); + + void Destroy(void); + + bool CanReportWifiWakeSourceTypeClientDriverDiagnostic; + +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WifiNetvAdapter, WifiNetvAdapterGetContext);
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/device.cpp b/network/wlan/wificx/drivercode/device.cpp new file mode 100644 index 00000000..0e04d562 --- /dev/null +++ b/network/wlan/wificx/drivercode/device.cpp @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +#include "precomp.h" + +#include "adapter.h" +#include "device.h" +#include "device.tmh" + +_Use_decl_annotations_ +NTSTATUS EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resourcesRaw, WDFCMRESLIST resourcesTranslated) +{ + UNREFERENCED_PARAMETER(resourcesRaw); + UNREFERENCED_PARAMETER(resourcesTranslated); + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WifiHAL::_Create(device), + "WifiHAL::_Create failed"); + + WFCInfo("Device=0x%p", device); + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resourcesTranslated) +{ + UNREFERENCED_PARAMETER(resourcesTranslated); + + WFCInfo("Device=0x%p", device); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS EvtWifiDeviceCreateAdapter(WDFDEVICE Device, NETADAPTER_INIT* AdapterInit) +{ + if (WifiAdapterInitGetType(AdapterInit) != WIFI_ADAPTER_EXTENSIBLE_STATION) + { + WFCError("%!FUNC!: Unsupported adapter type = 0x%x != 0x%x", WifiAdapterInitGetType(AdapterInit), WIFI_ADAPTER_EXTENSIBLE_STATION); + return STATUS_NOT_SUPPORTED; + } + + NET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks; + NET_ADAPTER_DATAPATH_CALLBACKS_INIT(&datapathCallbacks, EvtAdapterCreateTxQueue, EvtAdapterCreateRxQueue); + + NetAdapterInitSetDatapathCallbacks(AdapterInit, &datapathCallbacks); + + WDF_OBJECT_ATTRIBUTES adapterAttributes; + WDF_OBJECT_ATTRIBUTES_INIT(&adapterAttributes); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&adapterAttributes, WifiNetvAdapter); + adapterAttributes.EvtCleanupCallback = EvtAdapterCleanup; + +#ifdef NETV_SUPPORT_TX_DEMUXING + WIFI_ADAPTER_TX_DEMUX peerInfoDemux; + WIFI_ADAPTER_TX_PEER_ADDRESS_DEMUX_INIT(&peerInfoDemux, MaxNumOfPeers); + WifiAdapterInitAddTxDemux(AdapterInit, &peerInfoDemux); +#endif // NETV_SUPPORT_TX_DEMUXING + + + NETADAPTER netAdapter; + NTSTATUS ntStatus = NetAdapterCreate(AdapterInit, &adapterAttributes, &netAdapter); + if (!NT_SUCCESS(ntStatus)) + { + WFCError("%!FUNC!: NetAdapterCreate failed, status=0x%x", ntStatus); + return ntStatus; + } + + ntStatus = WifiAdapterInitialize(netAdapter); + ASSERT(NT_SUCCESS(ntStatus)); + if (!NT_SUCCESS(ntStatus)) + { + WFCError("%!FUNC!: WifiAdapterInitialize failed with %!STATUS!", ntStatus); + return ntStatus; + } + auto wifiNetvAdapter = new (reinterpret_cast<void*>(WifiNetvAdapterGetContext(netAdapter))) WifiNetvAdapter(netAdapter, Device); + ntStatus = wifiNetvAdapter->Initialize(); + if (!NT_SUCCESS(ntStatus)) + { + WFCError("%!FUNC!: WifiNetvAdapter::Initialize failed with %!STATUS!", ntStatus); + return ntStatus; + } + + ntStatus = wifiNetvAdapter->AdapterStart(); + ASSERT(NT_SUCCESS(ntStatus)); + if (!NT_SUCCESS(ntStatus)) + { + WFCError("%!FUNC!: WifiNetvAdapter::AdapterStart failed with %!STATUS!", ntStatus); + return ntStatus; + } + + auto wifiNetvDevice = WifiGetIhvDeviceContext(Device); + wifiNetvDevice->netAdapters[WifiAdapterGetPortId(netAdapter)] = netAdapter; + + WFCInfo("%!FUNC!: Success!"); + return ntStatus; +} + +_Use_decl_annotations_ +void EvtAdapterCleanup(_In_ WDFOBJECT NetAdapter) +{ + TraceEntry(); + auto wifiNetvAdapter = WifiNetvAdapterGetContext(NetAdapter); + wifiNetvAdapter->Destroy(); + TraceExit(STATUS_SUCCESS); +} + + +_Use_decl_annotations_ +NTSTATUS EvtWifiDeviceCreateWifiDirectDevice(WDFDEVICE, WIFIDIRECT_DEVICE_INIT*) +{ + NTSTATUS status = STATUS_SUCCESS; + TraceEntry(); + TraceExit(status); + return status; +} + + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateTxQueue(NETADAPTER Adapter, NETTXQUEUE_INIT* Init) +{ + TraceEntry(); + return WifiNetvAdapterGetContext(Adapter)->CreateTxQueue(Init); +} + +_Use_decl_annotations_ +NTSTATUS +EvtAdapterCreateRxQueue(NETADAPTER Adapter, NETRXQUEUE_INIT* Init) +{ + TraceEntry(); + return WifiNetvAdapterGetContext(Adapter)->CreateRxQueue(Init); +} diff --git a/network/wlan/wificx/drivercode/device.h b/network/wlan/wificx/drivercode/device.h new file mode 100644 index 00000000..c0dfac3c --- /dev/null +++ b/network/wlan/wificx/drivercode/device.h @@ -0,0 +1,29 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once +#include "wifiHAL.h" +EVT_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware; + +EVT_WIFI_DEVICE_CREATE_ADAPTER EvtWifiDeviceCreateAdapter; +EVT_WIFI_DEVICE_CREATE_WIFIDIRECTDEVICE EvtWifiDeviceCreateWifiDirectDevice; +EVT_WIFI_DEVICE_SEND_COMMAND EvtWifiDeviceSendCommand; +EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtAdapterCleanup; + +EVT_NET_ADAPTER_CREATE_TXQUEUE EvtAdapterCreateTxQueue; +EVT_NET_ADAPTER_CREATE_RXQUEUE EvtAdapterCreateRxQueue; + +typedef struct _WIFI_IHV_DEVICE_CONTEXT +{ + // + // Do not add field variable before WdfTriageInfoPtr. + // NetAdapterCx carving code requires the first field of WDF context + // to be a pointer to WDF_TRIAGE_INFO. + // + void* WdfTriageInfoPtr; + WDFDEVICE WdfDevice; + TLV_CONTEXT TlvContext; + NETADAPTER netAdapters[5]{}; +} WIFI_IHV_DEVICE_CONTEXT, * PWIFI_IHV_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WIFI_IHV_DEVICE_CONTEXT, WifiGetIhvDeviceContext); +static_assert(FIELD_OFFSET(WIFI_IHV_DEVICE_CONTEXT, WdfTriageInfoPtr) == 0); diff --git a/network/wlan/wificx/drivercode/driver.cpp b/network/wlan/wificx/drivercode/driver.cpp new file mode 100644 index 00000000..bbc4d151 --- /dev/null +++ b/network/wlan/wificx/drivercode/driver.cpp @@ -0,0 +1,210 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +#include "precomp.h" + +#include "device.h" +#include "driver.h" +#include "driver.tmh" + +NTSTATUS DriverEntry( + _In_ PDRIVER_OBJECT driverObject, + _In_ PUNICODE_STRING registryPath) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry specifies the other entry + points in the function driver, such as EvtDevice and DriverUnload. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DRIVER_CONFIG driverConfig{}; + WDF_OBJECT_ATTRIBUTES attributes; + + // + // Initialize WPP Tracing + // + WPP_INIT_TRACING(driverObject, registryPath); + + // Since WPP tracing is now initialized, we can use Trace functions + TraceEntry(); + + // + // Register a cleanup callback so that we can call WPP_CLEANUP when + // the framework driver object is deleted during driver unload. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = EvtWifiDriverContextCleanup; + + WDF_DRIVER_CONFIG_INIT(&driverConfig, EvtWifiDriverDeviceAdd); + driverConfig.DriverPoolTag = WIFI_DRIVER_DEFAULT_POOL_TAG; + + status = WdfDriverCreate(driverObject, registryPath, &attributes, &driverConfig, WDF_NO_HANDLE); + if (!NT_SUCCESS(status)) + { + WFCError("WdfDriverCreate failed %!STATUS!", status); + WPP_CLEANUP(driverObject); + return status; + } + + TraceExit(status); + + return status; +} + +NTSTATUS EvtWifiDriverDeviceAdd(_In_ WDFDRIVER driver, _Inout_ PWDFDEVICE_INIT deviceInit) +/*++ +Routine Description: + + EvtWifiDriverDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(driver); + + TraceEntry(); + + NTSTATUS status = STATUS_SUCCESS; + + // Configure the device init for NetAdapterCx (Data Path) + status = NetDeviceInitConfig(deviceInit); + if (!NT_SUCCESS(status)) + { + WFCError("NetDeviceInitConfig failed, status=0x%x", status); + goto Exit; + } + + // Configure the device init for WifiCx (Control Path) + status = WifiDeviceInitConfig(deviceInit); + if (!NT_SUCCESS(status)) + { + WFCError("WifiDeviceInitConfig failed, status=0x%x", status); + goto Exit; + } + + // Set PnP and Power Callbacks. + // [Scope: Only PrepareHardware and ReleaseHardware are implemented in this sample.] + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware; + WdfDeviceInitSetPnpPowerEventCallbacks(deviceInit, &pnpPowerCallbacks); + + // [Scope: ArmWake and DisarmWake are not implemented in this sample.] + //WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks; + //WdfDeviceInitSetPowerPolicyEventCallbacks(deviceInit, &powerPolicyCallbacks); + + WDFDEVICE wdfIhvDevice{}; + // Create the device object context to store the device specific information + WDF_OBJECT_ATTRIBUTES ihvDeviceAttributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ihvDeviceAttributes, WIFI_IHV_DEVICE_CONTEXT); + + status = WdfDeviceCreate(&deviceInit, &ihvDeviceAttributes, &wdfIhvDevice); + if (!NT_SUCCESS(status)) + { + WFCError("WdfDeviceCreate failed, status=0x%x", status); + goto Exit; + } + + // + // Create a device interface so that applications can find and talk + // to us. + // + status = WdfDeviceCreateDeviceInterface(wdfIhvDevice, &GUID_WIFICX_SAMPLE_CLIENT_INTERFACE, nullptr); + if (!NT_SUCCESS(status)) + { + WFCError("WdfDeviceCreateDeviceInterface failed with status=0x%x", status); + goto Exit; + } + + // Initialize WifiCx device now that the WDFDEVICE has been created. + // In short the WifICx is the "wdf managed WDI", so the Wdi core + // concepts still applies. + WIFI_DEVICE_CONFIG wifiDeviceConfig; + WIFI_DEVICE_CONFIG_INIT( + &wifiDeviceConfig, + WDI_VERSION_LATEST, // The "WDI" version supported by this Ihv driver + EvtWifiDeviceSendCommand, // The Wdi command and task, now called "wifirequest". + EvtWifiDeviceCreateAdapter, // The Wdi "ports", now support by the netadapter instances. + EvtWifiDeviceCreateWifiDirectDevice); // [Scope: No WiFi Direct support in this sample] + + // Initialize the WifiCx device with the configuration above to let OS side ready. + status = WifiDeviceInitialize(wdfIhvDevice, &wifiDeviceConfig); + if (!NT_SUCCESS(status)) + { + WFCError("WifiDeviceInitialize failed, status=0x%x", status); + goto Exit; + } + + // Get a pointer to the device context structure that we just associated + // with the device object. We define this structure in the device.h + // header file. WifiGetIhvDeviceContext is an inline function generated by + // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h. + // This function will do the type checking and return the device context. + // If you pass a wrong object handle it will return NULL and assert if + // run under framework verifier mode. + auto deviceIhvContext = WifiGetIhvDeviceContext(wdfIhvDevice); + deviceIhvContext->WdfDevice = wdfIhvDevice; + deviceIhvContext->WdfTriageInfoPtr = WdfGetTriageInfo(); + + deviceIhvContext->TlvContext.AllocationContext = 0; + deviceIhvContext->TlvContext.PeerVersion = WifiDeviceGetOsWdiVersion(wdfIhvDevice); + +Exit: + TraceExit(status); + return status; +} + +void EvtWifiDriverContextCleanup(_In_ WDFOBJECT DriverObject) +/*++ +Routine Description: + + Free all the resources allocated in DriverEntry. + +Arguments: + + DriverObject - handle to a WDF Driver object. + +Return Value: + + VOID. + +--*/ +{ +#ifndef _KERNEL_MODE + // follow https://github.com/MicrosoftDocs/windows-driver-docs/blob/staging/windows-driver-docs-pr/wdf/using-wpp-software-tracing-in-kmdf-and-umdf-2-drivers.md + // because UMDF drivers use the kernel-mode signatures of these macros for initializing and cleaning up tracing, the calls look identical for KMDF and UMDF. + UNREFERENCED_PARAMETER(DriverObject); +#endif // !_KERNEL_MODE + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(static_cast<WDFDRIVER>(DriverObject))); +} diff --git a/network/wlan/wificx/drivercode/driver.h b/network/wlan/wificx/drivercode/driver.h new file mode 100644 index 00000000..8573b30e --- /dev/null +++ b/network/wlan/wificx/drivercode/driver.h @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +#pragma once +#include "precomp.h" + +WDF_EXTERN_C_START + +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD EvtWifiDriverDeviceAdd; +EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtWifiDriverContextCleanup; + +WDF_EXTERN_C_END
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/memorymanagement.cpp b/network/wlan/wificx/drivercode/memorymanagement.cpp new file mode 100644 index 00000000..088bad88 --- /dev/null +++ b/network/wlan/wificx/drivercode/memorymanagement.cpp @@ -0,0 +1,149 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#include "precomp.h" + +#ifndef _KERNEL_MODE +#include <intrin.h> // for _ReturnAddress for user mode +#endif // UM + +typedef struct _PLACEMENT_NEW_ALLOCATION_CONTEXT +{ + size_t cbMaxSize; + _Field_size_bytes_(cbMaxSize) void* pbBuffer; +} PLACEMENT_NEW_ALLOCATION_CONTEXT, * PPLACEMENT_NEW_ALLOCATION_CONTEXT; +typedef const PLACEMENT_NEW_ALLOCATION_CONTEXT* PCPLACEMENT_NEW_ALLOCATION_CONTEXT; + +// for FreeWdfMemoryBuffer to correct get +// the handle to free the memory +struct WIFI_IHV_MEMORY_HEADER +{ + size_t HeaderSize; + WDFMEMORY WdfMemoryHandle; +}; + +// for tracking memory leaks +struct WIFI_IHV_MEMORY_CONTEXT +{ + size_t ContextSize; + void* pvCaller; +}; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WIFI_IHV_MEMORY_CONTEXT, GetWificxIhvMemoryContextFromHandle); + + +void* AllocateWdfMemoryBuffer(size_t Size, _In_ void* CallerForMemoryLeakTracking) +{ + size_t totalSize = 0; + if (!NT_SUCCESS(Wifi::SizeTAddSafe(Size, sizeof(WIFI_IHV_MEMORY_HEADER), &totalSize))) + { + NT_ASSERT(FALSE); + WFCError("Failed to calculate total size"); + return nullptr; + } + + // allocate the context memory to store the WIFI_IHV_MEMORY_CONTEXT + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WIFI_IHV_MEMORY_CONTEXT); + WDFMEMORY wdfMemoryBufferHandle = WDF_NO_HANDLE; + void* pWdfMemoryBuffer = nullptr; + + if (!NT_SUCCESS(WdfMemoryCreate(&attributes, NonPagedPoolNx, WIFI_DRIVER_DEFAULT_POOL_TAG, totalSize, &wdfMemoryBufferHandle, &pWdfMemoryBuffer))) + { + WFCError("Failed to allocate memory buffer"); + return nullptr; + } + + RtlZeroMemory(pWdfMemoryBuffer, totalSize); + + // store the wdf memory handle in the header for FreeWdfMemoryBuffer to find the handle + WIFI_IHV_MEMORY_HEADER* pMemoryHeader = static_cast<WIFI_IHV_MEMORY_HEADER*>(pWdfMemoryBuffer); + pMemoryHeader->HeaderSize = sizeof(WIFI_IHV_MEMORY_HEADER); + pMemoryHeader->WdfMemoryHandle = wdfMemoryBufferHandle; + + // store the caller and caller's caller for tracking memory leaks + auto memoryContext = GetWificxIhvMemoryContextFromHandle(wdfMemoryBufferHandle); + RtlZeroMemory(memoryContext, sizeof(WIFI_IHV_MEMORY_CONTEXT)); + memoryContext->ContextSize = sizeof(WIFI_IHV_MEMORY_CONTEXT); + memoryContext->pvCaller = CallerForMemoryLeakTracking; + + // hide the wdf memory header to the caller. + const ULONG_PTR wdfMemoryWithHeaderBuffer = reinterpret_cast<ULONG_PTR>(pWdfMemoryBuffer); + ULONG_PTR wdfMemoryPayloadOnlyBuffer{ 0 }; + if (!NT_SUCCESS(Wifi::ULongPtrAddSafe(wdfMemoryWithHeaderBuffer, sizeof(WIFI_IHV_MEMORY_HEADER), &wdfMemoryPayloadOnlyBuffer))) + { + NT_ASSERT(FALSE); + WFCError("Failed to calculate payload buffer address"); + return nullptr; + } + + return reinterpret_cast<void*>(wdfMemoryPayloadOnlyBuffer); +} + +void FreeWdfMemoryBuffer(_In_opt_ void* pBuffer) +{ + if (pBuffer == nullptr) // existing wdi code not checking for nullptr before delete, so we have to leave it as is + { + return; + } + const ULONG_PTR wdfMemoryPayloadOnlyBuffer = reinterpret_cast<ULONG_PTR>(pBuffer); + ULONG_PTR wdfMemoryWithHeaderBuffer{ 0 }; + if (!NT_SUCCESS(Wifi::ULongPtrSubSafe(wdfMemoryPayloadOnlyBuffer, sizeof(WIFI_IHV_MEMORY_HEADER), &wdfMemoryWithHeaderBuffer))) + { + NT_ASSERT(FALSE); + WFCError("Failed to calculate header buffer address"); + return; + } + + const auto wificxMemoryHeader = static_cast<WIFI_IHV_MEMORY_HEADER*>(reinterpret_cast<void*>(wdfMemoryWithHeaderBuffer)); + + // This is memory corruption detection logic, + // keep it, don't remove it. + NT_ASSERT(wificxMemoryHeader->HeaderSize == sizeof(WIFI_IHV_MEMORY_HEADER)); + + WdfObjectDelete(wificxMemoryHeader->WdfMemoryHandle); +} + +_Ret_writes_bytes_maybenull_(_Size) void* PlacementNewHelper(size_t _Size, PCPLACEMENT_NEW_ALLOCATION_CONTEXT AllocationContext) +{ + if (_Size <= AllocationContext->cbMaxSize) + { + RtlZeroMemory(AllocationContext->pbBuffer, _Size); + return AllocationContext->pbBuffer; + } + WFCError( + "Placement operator new called with insufficient buffer space (desired: %Iu, availible: %Iu)", _Size, AllocationContext->cbMaxSize); + return nullptr; +} + +void* __cdecl operator new(size_t Size) noexcept +{ + return AllocateWdfMemoryBuffer(Size, _ReturnAddress()); +} + +__forceinline void* __cdecl operator new(size_t _Size, ULONG_PTR AllocationContext) noexcept // for WIFICX TLV +{ + if (AllocationContext != 0) + { + return PlacementNewHelper(_Size, (PPLACEMENT_NEW_ALLOCATION_CONTEXT)AllocationContext); + } + return AllocateWdfMemoryBuffer(_Size, _ReturnAddress()); +} + +void __cdecl operator delete(void* pData) noexcept +{ + FreeWdfMemoryBuffer(pData); +} + +void __cdecl operator delete[](void* pData) noexcept +{ + FreeWdfMemoryBuffer(pData); +} + +void __cdecl operator delete(void* pData, ULONG_PTR) noexcept // For WIFICX TLV +{ + FreeWdfMemoryBuffer(pData); +} + +void __cdecl operator delete[](void* pData, ULONG_PTR) noexcept // For WIFICX TLV +{ + FreeWdfMemoryBuffer(pData); +}
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/precomp.h b/network/wlan/wificx/drivercode/precomp.h new file mode 100644 index 00000000..1b0f808e --- /dev/null +++ b/network/wlan/wificx/drivercode/precomp.h @@ -0,0 +1,33 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#ifdef _KERNEL_MODE + #include <ntddk.h> +#else + #include <windows.h> + #include <ndis/types.h> // For NDIS_STATUS + #include <ndis/status.h> // For NDIS_STATUS codes + #include <ntddndis.h> +#endif +// WDF Headers +#include <wdf.h> + +// Network Device Headers +#include <netadaptercx.h> +#include <netiodef.h> + +// WIFI Device Headers +#include <wificx.h> +#include "umkmfusion.h" +#include "dot11wificxintf.h" +#include "dot11wificxtypes.hpp" +#include "TLVGeneratorParser.hpp" +#include "SharedTypes.h" + +// WPP Tracing Headers +#include "trace.h" + +// Minimal placement-new to match operator new(size_t, void*) +// TLV generator/parser memory interface has the ULONG_PTR version +inline void* operator new(size_t, void* p) noexcept { return p; } +inline void operator delete(void*, void*) noexcept { /* no-op */ } diff --git a/network/wlan/wificx/drivercode/trace.h b/network/wlan/wificx/drivercode/trace.h new file mode 100644 index 00000000..324e1c87 --- /dev/null +++ b/network/wlan/wificx/drivercode/trace.h @@ -0,0 +1,183 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#pragma once +#ifndef TRACE_H +#define TRACE_H + +#define WPP_USE_TRACE_LEVELS + +// 21BA7B61-05F8-41F1-9048-C09493DCFE38 +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID(WdiLibraryCtlGuid, (21BA7B61, 05F8, 41F1, 9048, C09493DCFE38), WPP_DEFINE_BIT(DUMMY)) + +//#define WPP_LEVEL_EXP_ENABLED(LEVEL, EXP) WPP_LEVEL_ENABLED(LEVEL) +//#define WPP_LEVEL_EXP_LOGGER(LEVEL, EXP) WPP_LEVEL_LOGGER(LEVEL) + + +#define WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags) WPP_CONTROL(WPP_BIT_##flags).AutoLogContext, lvl, WPP_BIT_##flags +#define WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags) \ + (WPP_LEVEL_ENABLED(lvl) || lvl < TRACE_LEVEL_VERBOSE || WPP_CONTROL(WPP_BIT_##flags).AutoLogVerboseEnabled) + +#define WPP_RECORDER_LEVEL_ARGS(LEVEL) WPP_RECORDER_LEVEL_FLAGS_ARGS(LEVEL, DUMMY) +#define WPP_RECORDER_LEVEL_FILTER(LEVEL) WPP_RECORDER_LEVEL_FLAGS_FILTER(LEVEL, DUMMY) + +#define WPP_RECORDER_LEVEL_EXP_FILTER(LEVEL, EXP) WPP_RECORDER_LEVEL_FILTER(LEVEL) +#define WPP_RECORDER_LEVEL_EXP_ARGS(LEVEL, EXP) WPP_RECORDER_LEVEL_ARGS(LEVEL) + +// Suppress warnings about constants in logical expressions because the +// level is often a constant +#define WPP_LEVEL_PRE(LEVEL) __pragma(warning(suppress : 25039 25040)) +#define WPP_LEVEL_EXP_PRE(LEVEL, EXP) __pragma(warning(suppress : 25039 25040)) + +#define TraceEntry(...) +#define TraceExit(Status) +#define WFCTrace(Format, ...) +#define WFCError(Format, ...) +#define WFCInfo(Format, ...) + +// begin_wpp config +// USEPREFIX (TraceEntry, "%!STDPREFIX!"); +// FUNC TraceEntry{LEVEL=TRACE_LEVEL_VERBOSE}(...); +// USESUFFIX (TraceEntry, "--> %!FUNC!"); +// end_wpp + +// begin_wpp config +// USEPREFIX (TraceExit, "%!STDPREFIX!"); +// FUNC TraceExit{LEVEL=TRACE_LEVEL_VERBOSE}(EXP); +// USESUFFIX (TraceExit, "<-- %!FUNC!: 0x%x", EXP); +// end_wpp + +// +// Flat-C trace commands +// +// begin_wpp config +// +// USEPREFIX (WFCError, "%!STDPREFIX! %!FUNC!: [ERROR]"); +// FUNC WFCError{LEVEL=TRACE_LEVEL_ERROR}(MSG, ...); +// +// USEPREFIX (WFCInfo, "%!STDPREFIX! %!FUNC!: [INFO]"); +// FUNC WFCInfo{LEVEL=TRACE_LEVEL_INFORMATION}(MSG, ...); +// +// USEPREFIX (WFCTrace, "%!STDPREFIX! %!FUNC!: [TRACE]"); +// FUNC WFCTrace{LEVEL=TRACE_LEVEL_VERBOSE}(MSG, ...); +// +// end_wpp +// + +#define MACRO_START \ + do \ + { +#define MACRO_END \ + } \ + while (0) + +// +// WPP Macros: WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG +// +// begin_wpp config +// FUNC WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG{COMPNAME=DUMMY,LEVEL=TRACE_LEVEL_ERROR}(NTEXPR,MSG,...); +// USEPREFIX (WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG, "%!STDPREFIX! !! WifiIhv - %!FUNC!: "); +// USESUFFIX (WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG, " [status=%!STATUS!]", nt__wpp); +// end_wpp + +#define WPP_COMPNAME_LEVEL_NTEXPR_PRE(comp, level, ntexpr) \ + MACRO_START NTSTATUS nt__wpp = (ntexpr); \ + if (!NT_SUCCESS(nt__wpp)) \ + { +#define WPP_COMPNAME_LEVEL_NTEXPR_POST(comp, level, ntexpr) \ + ; \ + return nt__wpp; \ + } \ + MACRO_END +#define WPP_RECORDER_COMPNAME_LEVEL_NTEXPR_FILTER(comp, level, ntexpr) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, comp) +#define WPP_RECORDER_COMPNAME_LEVEL_NTEXPR_ARGS(comp, level, ntexpr) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, comp) + +// +// WPP Macros: WX_RETURN_INSUFFICIENT_RESOURCES_IF_NULL_MSG +// +// begin_wpp config +// FUNC WX_RETURN_INSUFFICIENT_RESOURCES_IF_NULL_MSG{COMPNAME=DUMMY,LEVEL=TRACE_LEVEL_ERROR}(PTR2,MSG,...); +// USEPREFIX (WX_RETURN_INSUFFICIENT_RESOURCES_IF_NULL_MSG, "%!STDPREFIX! !! WifiIhv - %!FUNC!: "); +// USESUFFIX (WX_RETURN_INSUFFICIENT_RESOURCES_IF_NULL_MSG, "%!s! is null", #PTR2); +// end_wpp + +#define WPP_COMPNAME_LEVEL_PTR2_PRE(comp, level, ptr) \ + MACRO_START if ((ptr == nullptr)) \ + { +#define WPP_COMPNAME_LEVEL_PTR2_POST(comp, level, ptr) \ + ; \ + return STATUS_INSUFFICIENT_RESOURCES; \ + } \ + MACRO_END +#define WPP_RECORDER_COMPNAME_LEVEL_PTR2_FILTER(comp, level, ptr) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, comp) +#define WPP_RECORDER_COMPNAME_LEVEL_PTR2_ARGS(comp, level, ptr) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, comp) + +// +// WPP Macros: WX_RETURN_IF_NULL_MSG +// +// begin_wpp config +// FUNC WX_RETURN_IF_NULL_MSG{COMPNAME=DUMMY,LEVEL=TRACE_LEVEL_ERROR}(PTR3,MSG,...); +// USEPREFIX (WX_RETURN_IF_NULL_MSG, "%!STDPREFIX! !! WifiIhv - %!FUNC!: "); +// USESUFFIX (WX_RETURN_IF_NULL_MSG, "%!s! is null", #PTR3); +// end_wpp + +#define WPP_COMPNAME_LEVEL_PTR3_PRE(comp, level, ptr) \ + MACRO_START if ((ptr == nullptr)) \ + { +#define WPP_COMPNAME_LEVEL_PTR3_POST(comp, level, ptr) \ + ; \ + return; \ + } \ + MACRO_END +#define WPP_RECORDER_COMPNAME_LEVEL_PTR3_FILTER(comp, level, ptr) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, comp) +#define WPP_RECORDER_COMPNAME_LEVEL_PTR3_ARGS(comp, level, ptr) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, comp) + +typedef struct _ByteArray +{ + USHORT usLength; + const void* pvBuffer; +} ByteArray; + +__inline ByteArray log_lenstr(ULONG len, const void* buf) +{ + ByteArray xs{}; + xs.usLength = (USHORT)len; + xs.pvBuffer = buf; + return xs; +} + +#define WPP_LOGHEXDUMP(x) \ + WPP_LOGPAIR(2, &((x).usLength)) \ + WPP_LOGPAIR((x).usLength, (x).pvBuffer) + +#define WPP_LOGANSISTRING(x) \ + WPP_LOGPAIR(2, &((x).usLength)) \ + WPP_LOGPAIR((x).usLength, (x).pvBuffer) + +#define WPP_LOGMACADDR(x) WPP_LOGPAIR(6, x) + +#define WPP_LOGDOT11SSID(x) \ + WPP_LOGPAIR(2, &((*(x)).uSSIDLength)) \ + WPP_LOGPAIR((*(x)).uSSIDLength, ((const char*)(*(x)).ucSSID)) + +// +// Custom types +// +// begin_wpp config +// +// DEFINE_CPLX_TYPE(HEXDUMP, WPP_LOGHEXDUMP, ByteArray, ItemHEXDump,"s", _HEX_, 0,2); +// WPP_FLAGS(-DLOG_HEXDUMP(len,str)=log_lenstr(len,str)); +// +// DEFINE_CPLX_TYPE(ANSISTRING, WPP_LOGANSISTRING, ByteArray, ItemPString,"s", _SSID_, 0,2); +// WPP_FLAGS(-DLOG_ANSISTRING(len,str)=log_lenstr(len,str)); +// +// DEFINE_CPLX_TYPE(DOT11SSID, WPP_LOGDOT11SSID, DOT11_SSID*, ItemPString,"s", _SSID_, 0,2); +// +// DEFINE_CPLX_TYPE(MACADDR, WPP_LOGMACADDR, DOT11_MAC_ADDRESS, ItemMACAddr,"s", _MAC_, 0); +// +// CUSTOM_TYPE(MESSAGE_ID, ItemEnum(WDI_TLV::ENUMS::MESSAGE_ID)); +// end_wpp +// + +#endif diff --git a/network/wlan/wificx/drivercode/umkmfusion.h b/network/wlan/wificx/drivercode/umkmfusion.h new file mode 100644 index 00000000..8f0db3f8 --- /dev/null +++ b/network/wlan/wificx/drivercode/umkmfusion.h @@ -0,0 +1,131 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once +#include "precomp.h" + +#include "winerror.h" + +#ifdef _KERNEL_MODE +#include "ntintsafe.h" +#else +#include "intsafe.h" +#endif + +namespace Wifi +{ + _inline + NTSTATUS ConvertHRESULTToNTSTATUS(HRESULT hr) { + if ((hr & FACILITY_NT_BIT) == FACILITY_NT_BIT) { + return static_cast<NTSTATUS>(hr & ~FACILITY_NT_BIT); // Strip NT bit safely + } + + // Trace the HRESULT value for diagnostics + return SUCCEEDED(hr) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; + } + + __inline + NTSTATUS ConvertNDISSTATUSToNTSTATUS(NDIS_STATUS NdisStatus) + { + if (NT_SUCCESS(NdisStatus) && NdisStatus != NDIS_STATUS_SUCCESS && NdisStatus != NDIS_STATUS_PENDING && + NdisStatus != NDIS_STATUS_INDICATION_REQUIRED) + { + // Case where an NDIS error is incorrectly mapped as a success by NT_SUCCESS macro + return STATUS_UNSUCCESSFUL; + } + else + { + switch (NdisStatus) + { + case NDIS_STATUS_BUFFER_TOO_SHORT: + return STATUS_BUFFER_TOO_SMALL; + break; + default: + return (NTSTATUS)NdisStatus; + break; + } + } + } + + __inline + NDIS_STATUS ConvertNTSTATUSToNDISSTATUS(NTSTATUS NtStatus) + { + if (NT_SUCCESS(NtStatus) && NtStatus != STATUS_PENDING && NtStatus != STATUS_NDIS_INDICATION_REQUIRED) + { + return NDIS_STATUS_SUCCESS; + } + else + { + switch (NtStatus) + { + case STATUS_BUFFER_TOO_SMALL: + return NDIS_STATUS_BUFFER_TOO_SHORT; + break; + default: + return (NDIS_STATUS)NtStatus; + break; + } + } + } + + _Must_inspect_result_ + _inline + NTSTATUS SizeTAddSafe(_In_ size_t Augend, _In_ size_t Addend, _Out_ _Deref_out_range_(== , Augend + Addend) size_t* pResult) + { +#ifdef _KERNEL_MODE + return RtlSizeTAdd(Augend, Addend, pResult); +#else + return ConvertHRESULTToNTSTATUS(SizeTAdd(Augend, Addend, pResult)); +#endif + } + + _Must_inspect_result_ + __inline + NTSTATUS ULongPtrAddSafe( + _In_ ULONGLONG ullAugend, + _In_ ULONGLONG ullAddend, + _Out_ _Deref_out_range_(== , ullAugend + ullAddend) ULONGLONG* pullResult) + { +#ifdef _KERNEL_MODE + return RtlULongPtrAdd(ullAugend, ullAddend, pullResult); +#else + return ConvertHRESULTToNTSTATUS(ULongPtrAdd(ullAugend, ullAddend, pullResult)); +#endif + } + + _Must_inspect_result_ + __inline + NTSTATUS ULongPtrSubSafe( + _In_ ULONGLONG ullMinuend, + _In_ ULONGLONG ullSubtrahend, + _Out_ _Deref_out_range_(== , ullMinuend - ullSubtrahend) ULONGLONG* pullResult) + { +#ifdef _KERNEL_MODE + return RtlULongPtrSub(ullMinuend, ullSubtrahend, pullResult); +#else + return ConvertHRESULTToNTSTATUS(ULongPtrSub(ullMinuend, ullSubtrahend, pullResult)); +#endif + } +} + +#ifndef _KERNEL_MODE +// TODO: Cleanup when EWDK contains the payload of https://microsoft.visualstudio.com/OS/_workitems/edit/58447986 +typedef enum _NDIS_FRAME_HEADER +{ + NdisFrameHeaderUndefined, + NdisFrameHeaderMac, + NdisFrameHeaderArp, + NdisFrameHeaderIPv4, + NdisFrameHeaderIPv6, + NdisFrameHeaderUdp, + NdisFrameHeaderMaximum +}NDIS_FRAME_HEADER, * PNDIS_FRAME_HEADER; + +typedef enum _NDIS_RECEIVE_FILTER_TEST +{ + NdisReceiveFilterTestUndefined, + NdisReceiveFilterTestEqual, + NdisReceiveFilterTestMaskEqual, + NdisReceiveFilterTestNotEqual, + NdisReceiveFilterTestMaximum +}NDIS_RECEIVE_FILTER_TEST, * PNDIS_RECEIVE_FILTER_TEST; +// End of TODO +#endif // !_KERNEL_MODE
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/wifihal.cpp b/network/wlan/wificx/drivercode/wifihal.cpp new file mode 100644 index 00000000..e7aaec1f --- /dev/null +++ b/network/wlan/wificx/drivercode/wifihal.cpp @@ -0,0 +1,1118 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#include "precomp.h" +#include "wifirequest.h" +#include "wifiHALtestdata.h" +#include "WifiHal.h" +#include "WifiHal.tmh" + +_Use_decl_annotations_ +NTSTATUS WifiHAL::_Create(WDFDEVICE Device) +{ + // Download firmware, initialize hardware, etc. + + // Create WifiHAL object and associate it with Device context after FW ready + WDF_OBJECT_ATTRIBUTES attributes; + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WifiHAL); + attributes.EvtCleanupCallback = WifiHAL::_OnCleanup; + + void* memory = nullptr; + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WdfObjectAllocateContext(Device, &attributes, &memory), "Failed to allocate WifiHAL context. Device=%p", Device); + + // Obtain the context and initialize it + auto* wifiHal = reinterpret_cast<WifiHAL*>(memory); + wifiHal->Initialize(Device, &WifiGetIhvDeviceContext(Device)->TlvContext); + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + wifiHal->WifiIhvSetDeviceCapabilities(), + "Failed to set device capabilities. Device=%p", Device); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +void WifiHAL::_OnCleanup(WDFOBJECT Object) +{ + UNREFERENCED_PARAMETER(Object); +} + +_Use_decl_annotations_ +void WifiHAL::Initialize(WDFDEVICE Device, PCTLV_CONTEXT TlvContext) +{ + m_Device = Device; + m_TlvContext = TlvContext; + m_CurrentRadioState = 1; // On by default + m_LastConnectEntryId = 0; + m_LastConnectTransactionId = 0; + m_LastAuthAlgo = WDI_AUTH_ALGO_UNKNOWN; + RtlZeroMemory(&m_ConnectedPeer, sizeof(m_ConnectedPeer)); + // Initialize link addresses and supported bands (previously in-class const init) + m_LocalLinkAddresses[0] = { 0x11, 0x01, 0x02, 0x03, 0x04, 0x21 }; + m_LocalLinkAddresses[1] = { 0x11, 0x01, 0x02, 0x03, 0x04, 0x22 }; + m_SupportedBands = (WDI_BAND_ID_2400 | WDI_BAND_ID_5000 | WDI_BAND_ID_6000); +} + +NTSTATUS WifiHAL::WifiIhvIsDeviceReadyForRequest() +{ + NTSTATUS status = + ((m_Device != WDF_NO_HANDLE) // Make sure device is initialized (since this is hardware abstraction layer, IHV can replace with firmware state) + && (WifiGetIhvDeviceContext(m_Device)->netAdapters[0] != WDF_NO_HANDLE) ? STATUS_SUCCESS : STATUS_DEVICE_NOT_READY);// In WIFICX, the logic sits on top of primary STA adapter, make sure it is initialized + if(NT_SUCCESS(status) == FALSE) + { + WFCError( + "Device not ready for request. Device=%p, primaryStaAdapter=%p", + m_Device, + (m_Device != WDF_NO_HANDLE) ? WifiGetIhvDeviceContext(m_Device)->netAdapters[0] : WDF_NO_HANDLE); + } + return status; +} + +NTSTATUS WifiHAL::WifiIhvGetPendingTransitionStatus() +{ + return m_LastConnectTransactionId ==0 ? STATUS_SUCCESS : STATUS_PENDING; +} + +NTSTATUS WifiHAL::WifiIhvSetDeviceCapabilities() +{ + WIFI_DEVICE_CAPABILITIES deviceCaps = {}; + WIFI_DEVICE_CAPABILITIES_INIT(&deviceCaps); + + deviceCaps.HardwareRadioState = TRUE; + deviceCaps.SoftwareRadioState = TRUE; + RtlCopyMemory(deviceCaps.FirmwareVersion, "1.0.0", sizeof("1.0.0")); + deviceCaps.ActionFramesSupported = TRUE; + deviceCaps.NumRxStreams = 1; + deviceCaps.NumTxStreams = 1; + deviceCaps.Support_eCSA = FALSE; + deviceCaps.MACAddressRandomization = FALSE; + deviceCaps.MACAddressRandomizationMask.Address[0] = 0; + deviceCaps.MACAddressRandomizationMask.Address[1] = 0; + deviceCaps.MACAddressRandomizationMask.Address[2] = 0; + deviceCaps.MACAddressRandomizationMask.Address[3] = 0xFF; + deviceCaps.MACAddressRandomizationMask.Address[4] = 0; + deviceCaps.MACAddressRandomizationMask.Address[5] = 0; + deviceCaps.BluetoothCoexistenceSupport = WDI_BLUETOOTH_COEXISTENCE_PERFORMANCE_MAINTAINED; + deviceCaps.SupportsNonWdiOidRequests = FALSE; + deviceCaps.FastTransitionSupported = TRUE; + deviceCaps.MU_MIMOSupported = FALSE; + deviceCaps.SAEAuthenticationSupported = TRUE; + deviceCaps.BSSTransitionSupported = TRUE; + deviceCaps.MBOSupported = FALSE; + deviceCaps.BeaconReportsImplemented = FALSE; + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WifiDeviceSetDeviceCapabilities(m_Device, &deviceCaps), + "Failed to set device capabilities"); + + WIFI_STATION_CAPABILITIES StationCaps = {}; + WIFI_STATION_CAPABILITIES_INIT(&StationCaps); + + StationCaps.ScanSSIDListSize = 4; + StationCaps.DesiredSSIDListSize = 1; + StationCaps.PrivacyExemptionListSize = 1; + StationCaps.KeyMappingTableSize = 32; + StationCaps.DefaultKeyTableSize = 4; + StationCaps.WEPKeyValueMaxLength = 0x20; + StationCaps.MaxNumPerSTA = 4; + StationCaps.SupportedQOSFlags = 0; + StationCaps.HostFIPSModeImplemented = FALSE; + StationCaps.MFPCapable = TRUE; + StationCaps.AutoPowerSaveMode = FALSE; + StationCaps.BSSListCachemanagement = FALSE; + StationCaps.ConnectBSSSelectionOverride = FALSE; + StationCaps.MaxNetworkOffloadListSize = 0; + StationCaps.HESSIDConnectionSupported = FALSE; + StationCaps.FTMAsInitiatorSupport = FALSE; + StationCaps.FTMNumberOfSupportedTargets = 0; + + const DOT11_AUTH_CIPHER_PAIR UnicastAlgos[] = { + {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_NONE}, + {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_WEP}, + {DOT11_AUTH_ALGO_WPA_PSK, DOT11_CIPHER_ALGO_CCMP}, + {DOT11_AUTH_ALGO_RSNA, DOT11_CIPHER_ALGO_CCMP}, + {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_TKIP}, + {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_CCMP}, + {DOT11_AUTH_ALGO_WPA3_ENT_192, DOT11_CIPHER_ALGO_GCMP_256}, + {DOT11_AUTH_ALGO_WPA3_ENT, DOT11_CIPHER_ALGO_CCMP}, + {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_GCMP_256}, + {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_CCMP}, + {DOT11_AUTH_ALGO_OWE, DOT11_CIPHER_ALGO_GCMP_256}, + {DOT11_AUTH_ALGO_OWE, DOT11_CIPHER_ALGO_CCMP}, + }; + + const DOT11_AUTH_CIPHER_PAIR McastMgmtAlgos[] = { + {DOT11_AUTH_ALGO_80211_OPEN, DOT11_CIPHER_ALGO_NONE}, + {DOT11_AUTH_ALGO_RSNA, DOT11_CIPHER_ALGO_BIP}, + {DOT11_AUTH_ALGO_RSNA_PSK, DOT11_CIPHER_ALGO_BIP}, + {DOT11_AUTH_ALGO_WPA3_SAE, DOT11_CIPHER_ALGO_BIP}, + {DOT11_AUTH_ALGO_WPA3_ENT, DOT11_CIPHER_ALGO_BIP}, + {DOT11_AUTH_ALGO_WPA3_ENT_192, DOT11_CIPHER_ALGO_BIP_GMAC_256}, + }; + + StationCaps.NumSupportedUnicastAlgorithms = ARRAYSIZE(UnicastAlgos); + StationCaps.UnicastAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(UnicastAlgos); + StationCaps.NumSupportedMulticastDataAlgorithms = ARRAYSIZE(UnicastAlgos); + StationCaps.MulticastDataAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(UnicastAlgos); + StationCaps.NumSupportedMulticastMgmtAlgorithms = ARRAYSIZE(McastMgmtAlgos); + StationCaps.MulticastMgmtAlgorithmsList = const_cast<PDOT11_AUTH_CIPHER_PAIR>(McastMgmtAlgos); + + WIFI_STA_BANDS_COMBINATION SecondaryStaBandsCombinations[] = { + {2, {WDI_BAND_ID_2400, WDI_BAND_ID_5000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}}, + {2, {WDI_BAND_ID_2400, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}}, + {2, {WDI_BAND_ID_5000, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN, WDI_BAND_ID_UNKNOWN}}, + {3, {WDI_BAND_ID_2400, WDI_BAND_ID_5000, WDI_BAND_ID_6000, WDI_BAND_ID_UNKNOWN}}, + }; + + StationCaps.NumSecondaryStaBandCombinations = ARRAYSIZE(SecondaryStaBandsCombinations); + StationCaps.SecondaryStaBandsCombinations = SecondaryStaBandsCombinations; + + WDI_MAC_ADDRESS MLOAddresses[] = { + {0x11, 0x01, 0x02, 0x03, 0x04, 0x21}, + {0x11, 0x01, 0x02, 0x03, 0x04, 0x22}, + }; + StationCaps.MaxMLOLinksSupported = ARRAYSIZE(MLOAddresses); + StationCaps.MLOAddressesList = MLOAddresses; + + RSNA_AKM_SUITE AkmsList[] = { + rsna_akm_1x, + rsna_akm_psk, + rsna_akm_ft_1x_sha256, + rsna_akm_ft_psk_sha256, + rsna_akm_1x_sha256, + rsna_akm_psk_sha256, + rsna_akm_sae_pmk256, + rsna_akm_1x_suite_b_sha384, + rsna_akm_owe, + rsna_akm_1x_sha384, + rsna_akm_sae_pmk384, + }; + StationCaps.NumAkmsSupported = ARRAYSIZE(AkmsList); + StationCaps.AkmsList = AkmsList; + + if (WIFI_IS_FIELD_AVAILABLE(WIFI_STATION_CAPABILITIES, MSCSSupported)) + { + StationCaps.MSCSSupported = true; + } + if (WIFI_IS_FIELD_AVAILABLE(WIFI_STATION_CAPABILITIES, DSCPToUPMappingSupported)) + { + StationCaps.DSCPToUPMappingSupported = true; + } + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WifiDeviceSetStationCapabilities(m_Device, &StationCaps), + "Failed to set station capabilities"); + + WIFI_BAND_CAPABILITIES BandCaps = {}; + WIFI_BAND_CAPABILITIES_INIT(&BandCaps); + + const WDI_PHY_TYPE Phy24GHz[] = { WDI_PHY_TYPE_ERP, WDI_PHY_TYPE_HE }; // g, ax + const WDI_PHY_TYPE Phy5GHz[] = { WDI_PHY_TYPE_OFDM, WDI_PHY_TYPE_HE, WDI_PHY_TYPE_EHT }; // a, ax, be + const WDI_PHY_TYPE Phy6GHz[] = { WDI_PHY_TYPE_HE, WDI_PHY_TYPE_EHT }; // ax, be + const WDI_PHY_TYPE pPhy60GHz[] = { WDI_PHY_TYPE_DMG }; // ad + const WDI_PHY_TYPE phyIHV[2] = { WDI_PHY_TYPE_OFDM, static_cast<WDI_PHY_TYPE>(WDI_PHY_TYPE_IHV_START + 1) }; + + // clang-format off + + const WDI_CHANNEL_MAPPING_ENTRY ChannelMap24[] = { + {1, 2412}, + {2, 2417}, + {3, 2422}, + {4, 2427}, + {5, 2432}, + {6, 2437}, + {7, 2442}, + {8, 2447}, + {9, 2452}, + {10, 2457}, + {11, 2462}, + {12, 2467}, // Not used in US + {13, 2472}, // Not used in US + {14, 2484}, // Allowed in Japan only + }; + + const WDI_CHANNEL_MAPPING_ENTRY ChannelMap5[] = { + {7, 5035}, // Not used in US + {8, 5040}, // Not used in US + {9, 5045}, // Not used in US + {11, 5055}, // Not used in US + {12, 5060}, // Not used in US + {16, 5080}, // Not used in US + {32, 5160}, // Unknown status + {34, 5170}, // Not used in US + {36, 5180}, + {38, 5190}, + {40, 5200}, + {42, 5210}, + {44, 5220}, + {46, 5230}, + {48, 5240}, + {50, 5250}, // DFS + {52, 5260}, // DFS + {54, 5270}, // DFS + {56, 5280}, // DFS + {58, 5290}, // DFS + {60, 5300}, // DFS + {62, 5310}, // DFS + {64, 5320}, // DFS + {68, 5340}, // Unknown status + {96, 5480}, // Unknown status + {100, 5500}, // DFS + {102, 5510}, // DFS + {104, 5520}, // DFS + {106, 5530}, // DFS + {108, 5540}, // DFS + {110, 5550}, // DFS + {112, 5560}, // DFS + {114, 5570}, // DFS + {116, 5580}, // DFS + {118, 5590}, // DFS + {120, 5600}, // DFS + {122, 5610}, // DFS + {124, 5620}, // DFS + {126, 5630}, // DFS + {128, 5640}, // DFS + {132, 5660}, // DFS + {134, 5670}, // DFS + {136, 5680}, // DFS + {138, 5690}, // DFS + {140, 5700}, // DFS + {142, 5710}, // DFS + {142, 5720}, // DFS + {144, 5730}, // DFS + {149, 5745}, + {151, 5755}, + {153, 5765}, + {155, 5785}, + {157, 5785}, + {159, 5795}, + {161, 5805}, + {165, 5825}, + {169, 5845}, // Not used in US + {173, 5865}, // Not used in US + {183, 4915}, // Not used in US + {184, 4920}, // Not used in US + {185, 4925}, // Not used in US + {187, 4935}, // Not used in US + {188, 4940}, // Not used in US + {189, 4945}, // Not used in US + {192, 4960}, // Not used in US + {196, 4980}, // Not used in US + }; + + const WDI_CHANNEL_MAPPING_ENTRY channelMap6[] = { + {1, 5955}, + {5, 5975}, // PSC Channel (1) + {9, 5995}, + + {13, 6015}, + {17, 6035}, + {21, 6055}, // PSC Channel (2) + {25, 6075}, + {29, 6095}, + + {33, 6115}, + {37, 6135}, // PSC Channel (3) + {41, 6155}, + {45, 6175}, + {49, 6195}, + + {53, 6215}, // PSC Channel (4) + {57, 6235}, + {61, 6255}, + {65, 6275}, + {69, 6295}, // PSC Channel (5) + + {73, 6315}, + {77, 6335}, + {81, 6355}, + {85, 6375}, // PSC Channel (6) + {89, 6395}, + + {93, 6415}, + {97, 6435}, + {101, 6455}, // PSC Channel (7) + {105, 6475}, + {109, 6495}, + + {113, 6515}, + {117, 6535}, // PSC Channel (8) + {121, 6555}, + {125, 6575}, + {129, 6595}, + + {133, 6615}, // PSC Channel (9) + {137, 6635}, + {141, 6655}, + {145, 6675}, + {149, 6695}, // PSC Channel (10) + + {153, 6715}, + {157, 6735}, + {161, 6755}, + {165, 6775}, // PSC Channel (11) + {169, 6795}, + + {173, 6815}, + {177, 6835}, + {181, 6855}, // PSC Channel (12) + {185, 6875}, + {189, 6895}, + + {193, 6915}, + {197, 6935}, // PSC Channel (13) + {201, 6955}, + {205, 6975}, + {209, 6995}, + + {213, 7015}, // PSC Channel (14) + {217, 7035}, + {221, 7055}, + {225, 7075}, + {229, 7095}, // PSC Channel (15) + + {233, 7115}, + {237, 7135}, + {241, 7155}, + {245, 7175}, + {249, 7195}, + + {253, 7215}, + }; + + const WDI_CHANNEL_MAPPING_ENTRY channelMap60[] = { + {1, 58320}, + {2, 60480}, + {3, 62640}, + {4, 64800}, + {5, 66960}, + {6, 69120}, + }; + + // clang-format on + + UINT32 ChannelWidth10Mhz = 10; + UINT32 ChannelWidth20Mhz = 20; + UINT32 channelWidth2160Mhz = 2160; + UINT32 pChannelWidth6Ghz[] = { 20, 40, 80, 160, 320 }; + + WIFI_BAND_INFO BandInfo[4] = {}; // Upto 4 bands + UINT32 bandInfoCount = 0; + + if (m_SupportedBands & WDI_BAND_ID_2400) + { + BandInfo[bandInfoCount].BandID = WDI_BAND_ID_2400; + BandInfo[bandInfoCount].BandState = TRUE; + BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy24GHz); + BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy24GHz); + BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(ChannelMap24); + BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(ChannelMap24); + BandInfo[bandInfoCount].NumChannelWidths = 1; + BandInfo[bandInfoCount].ChannelWidthList = &ChannelWidth10Mhz; + bandInfoCount++; + } + NT_ASSERT(bandInfoCount <= 1); + + if (m_SupportedBands & WDI_BAND_ID_5000) + { + BandInfo[bandInfoCount].BandID = WDI_BAND_ID_5000; + BandInfo[bandInfoCount].BandState = TRUE; + BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy5GHz); + BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy5GHz); + BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(ChannelMap5); + BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(ChannelMap5); + BandInfo[bandInfoCount].NumChannelWidths = 1; + BandInfo[bandInfoCount].ChannelWidthList = &ChannelWidth20Mhz; + bandInfoCount++; + } + NT_ASSERT(bandInfoCount <= 2); + + if (m_SupportedBands & WDI_BAND_ID_6000) + { + BandInfo[bandInfoCount].BandID = WDI_BAND_ID_6000; // 6 + BandInfo[bandInfoCount].BandState = TRUE; + BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(Phy6GHz); + BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(Phy6GHz); + BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(channelMap6); + BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(channelMap6); + BandInfo[bandInfoCount].NumChannelWidths = ARRAYSIZE(pChannelWidth6Ghz); + BandInfo[bandInfoCount].ChannelWidthList = pChannelWidth6Ghz; + bandInfoCount++; + } + + NT_ASSERT(bandInfoCount <= 3); + if (m_SupportedBands & WDI_BAND_ID_60000) + { + BandInfo[bandInfoCount].BandID = WDI_BAND_ID_60000; // 60 + BandInfo[bandInfoCount].BandState = TRUE; + BandInfo[bandInfoCount].NumValidPhyTypes = ARRAYSIZE(pPhy60GHz); + BandInfo[bandInfoCount].ValidPhyTypeList = const_cast<WDI_PHY_TYPE*>(pPhy60GHz); + BandInfo[bandInfoCount].NumValidChannelTypes = ARRAYSIZE(channelMap60); + BandInfo[bandInfoCount].ValidChannelTypes = const_cast<WDI_CHANNEL_MAPPING_ENTRY*>(channelMap60); + BandInfo[bandInfoCount].NumChannelWidths = 1; + BandInfo[bandInfoCount].ChannelWidthList = &channelWidth2160Mhz; + bandInfoCount++; + } + NT_ASSERT(bandInfoCount <= 4); + + BandCaps.NumBands = bandInfoCount; + BandCaps.BandInfoList = BandInfo; + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WifiDeviceSetBandCapabilities(m_Device, &BandCaps), + "Failed to set band capabilities"); + + WIFI_PHY_CAPABILITIES PhyCaps = {}; + WIFI_PHY_CAPABILITIES_INIT(&PhyCaps); + + WIFI_PHY_INFO PhyInfoList[3]; + + const WDI_DATA_RATE_ENTRY DataRateListErp[] = { + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2}, + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 4}, + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 22}, + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} }; + const WDI_DATA_RATE_ENTRY DataRateListOfdm[] = { + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2}, {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} }; + const WDI_DATA_RATE_ENTRY DataRateListEht[] = { + {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 2}, {WDI_DATA_RATE_RX_RATE | WDI_DATA_RATE_TX_RATE, 108} }; + + PhyInfoList[0].PhyType = WDI_PHY_TYPE_ERP; + PhyInfoList[0].NumberDataRateEntries = ARRAYSIZE(DataRateListErp); + RtlCopyMemory(&PhyInfoList[0].DataRateList, &DataRateListErp, sizeof(DataRateListErp)); + + PhyInfoList[1].PhyType = WDI_PHY_TYPE_HE; + PhyInfoList[1].NumberDataRateEntries = ARRAYSIZE(DataRateListOfdm); + RtlCopyMemory(&PhyInfoList[1].DataRateList, &DataRateListOfdm, sizeof(DataRateListOfdm)); + + PhyInfoList[2].PhyType = WDI_PHY_TYPE_EHT; + PhyInfoList[2].NumberDataRateEntries = ARRAYSIZE(DataRateListEht); + RtlCopyMemory(&PhyInfoList[2].DataRateList, &DataRateListEht, sizeof(DataRateListEht)); + + PhyCaps.NumPhyTypes = ARRAYSIZE(PhyInfoList); + PhyCaps.PhyInfoList = PhyInfoList; + + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG( + WifiDeviceSetPhyCapabilities(m_Device, &PhyCaps), + "Failed to set PHY capabilities"); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvReset(const WDI_TASK_DOT11_RESET_PARAMETERS& ResetParameters, const PWDI_MESSAGE_HEADER, UINT) +{ + if (0 == ResetParameters.Optional.ResetMACAddress_IsPresent) + { + WFCTrace("DOT11 Reset, set default MIB = %d, no MAC Address specified\n", ResetParameters.Dot11ResetParameters.SetDefaultMIB); + } + else + { + WFCTrace( + "DOT11 Reset, set default MIB = %d, MAC Address = %2x:%2x:%2x:%2x:%2x:%2x\n", + ResetParameters.Dot11ResetParameters.SetDefaultMIB, + ResetParameters.ResetMACAddress.Address[0], + ResetParameters.ResetMACAddress.Address[1], + ResetParameters.ResetMACAddress.Address[2], + ResetParameters.ResetMACAddress.Address[3], + ResetParameters.ResetMACAddress.Address[4], + ResetParameters.ResetMACAddress.Address[5]); + } + + // Reset the connection ID in case the previous connection attempt did not complete + m_LastConnectEntryId = 0; + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvSetRadioState(const WDI_SET_RADIO_STATE_PARAMETERS& RadioState, const PWDI_MESSAGE_HEADER pWdiHeader, UINT) +{ + WFCInfo("Setting OS requested Radio State: SoftwareRadioState=%u\n", RadioState.SoftwareRadioState); + if (RadioState.SoftwareRadioState != m_CurrentRadioState) + { + // Change the radio state + m_CurrentRadioState = RadioState.SoftwareRadioState; + + // Send the radio state indication + WDI_INDICATION_RADIO_STATUS_PARAMETERS RadioStatusParams = {}; + UINT8* pOutput = nullptr; + ULONG cbOutput = 0; + + RadioStatusParams.RadioState.HardwareState = TRUE; + RadioStatusParams.RadioState.SoftwareState = m_CurrentRadioState; + if (GenerateWdiIndicationRadioStatus(&RadioStatusParams, 0, m_TlvContext, &cbOutput, &pOutput) == NDIS_STATUS_SUCCESS) + { + WFCInfo("Indicate OS with Radio State: SoftwareRadioState=%u\n", m_CurrentRadioState); + WifiIhvSendUnsolicitedIndicationToOs(m_Device, pWdiHeader, WDI_INDICATION_RADIO_STATUS, pOutput, cbOutput); + FreeGenerated(pOutput); + } + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvScan(const WDI_SCAN_PARAMETERS& ScanParameters, const PWDI_MESSAGE_HEADER pWdiHeader, UINT) +{ + for (UINT8 connectEntry = 1; connectEntry < ConnectEntryId_MAX; connectEntry++) + { + if (m_SupportedBands & g_ConnectEntries[connectEntry].BandId) + { + PUCHAR pBssEntry = g_ConnectEntries[connectEntry].pTlvBssEntry; + // + // If currently connected, see if the connected entry should be skipped + // + if ((m_LastConnectEntryId != 0) && + (RtlCompareMemory(&m_ConnectedPeer, &pBssEntry[8], sizeof(DOT11_MAC_ADDRESS)) == sizeof(DOT11_MAC_ADDRESS))) + { + // Already connected, don't report this entry + continue; + } + + // TODO: Skip the IHV band as it is not being reported in capabilities + if (g_ConnectEntries[connectEntry].BandId == TESTMP_BAND_IHV) + { + continue; + } + + // Send the BSS entry indication + WifiIhvSendUnsolicitedIndicationToOs( + m_Device, + pWdiHeader, + WDI_INDICATION_BSS_ENTRY_LIST, + g_ConnectEntries[connectEntry].pTlvBssEntry, + g_ConnectEntries[connectEntry].TlvBssEntrySize); + } + } + + // + // See if the hidden network needs to be indicated + // + if ((ScanParameters.SSIDList.ElementCount > 0) && (ScanParameters.SSIDList.pElements[0].ElementCount == 8) && + (ScanParameters.SSIDList.pElements[0].pElements[4] == 'H') && (ScanParameters.SSIDList.pElements[0].pElements[5] == 'I') && + (ScanParameters.SSIDList.pElements[0].pElements[6] == 'D') && (ScanParameters.SSIDList.pElements[0].pElements[7] == 'E')) + { + WifiIhvSendUnsolicitedIndicationToOs( + m_Device, pWdiHeader, WDI_INDICATION_BSS_ENTRY_LIST, s_TLV_BSS_Entry_ProbeResponse_8_Hidden, sizeof(s_TLV_BSS_Entry_ProbeResponse_8_Hidden)); + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvConnect(const WDI_TASK_CONNECT_PARAMETERS& ConnectParameters, const PWDI_MESSAGE_HEADER pWdiHeader, UINT) +{ + NT_ASSERT(m_LastConnectEntryId == 0); +#ifdef NETV_SUPPORT_TX_DEMUXING + if (m_LastConnectEntryId != 0) // Not Disconnected State + { + WifiAdapterRemovePeer( + WifiGetIhvDeviceContext(m_Device)->netAdapters[pWdiHeader->PortId], + reinterpret_cast<NET_EUI48_ADDRESS*>(&m_ConnectedPeer)); + } +#endif //NETV_SUPPORT_TX_DEMUXING + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(WifiIhvPerformAssociation( + &ConnectParameters.PreferredBSSEntryList, &ConnectParameters.ConnectParameters.AuthenticationAlgorithms, pWdiHeader), + "Failed to perform association"); + + // + // WPA3-SAE requires the SAE Exchange, so do not complete the Connection request until the SAE exchange is complete + // + if (WDI_AUTH_ALGO_WPA3_SAE == m_LastAuthAlgo) + { + m_LastConnectTransactionId = pWdiHeader->TransactionId; + } + else + { + m_LastConnectTransactionId = 0; + } + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvSendLinkStateIndication(_In_ PWDI_MESSAGE_HEADER pWdiHeader, ULONG numLinks) +{ + // Report link quality + NTSTATUS ntStatus = STATUS_SUCCESS; + PWIFI_IHV_DEVICE_CONTEXT pDeviceContext = WifiGetIhvDeviceContext(m_Device); + WDI_INDICATION_LINK_STATE_CHANGE_PARAMETERS linkStateChangeParameters = {}; + WDI_LINK_INFO_CONTAINER pLinkInfo[2] = {}; + UINT8* pOutput = nullptr; + ULONG cbOutput = 0; + + RtlCopyMemory( + &linkStateChangeParameters.LinkStateChangeParameters.PeerMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS)); + linkStateChangeParameters.LinkStateChangeParameters.TxLinkSpeed = 30000; + linkStateChangeParameters.LinkStateChangeParameters.RxLinkSpeed = 30000; + linkStateChangeParameters.LinkStateChangeParameters.LinkQuality = 56; + + // Default linkId for non-Mlo connections is 0 + pLinkInfo[0].LinkID = 0; + RtlCopyMemory(&pLinkInfo[0].LocalLinkMACAddress, &m_LocalLinkAddresses[0], sizeof(DOT11_MAC_ADDRESS)); + RtlCopyMemory(&pLinkInfo[0].PeerLinkMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS)); + pLinkInfo[0].ChannelNumber = 6; + pLinkInfo[0].BandId = WDI_BAND_ID_2400; + pLinkInfo[0].RSSI = -50; + pLinkInfo[0].Bandwidth = 40; + pLinkInfo[0].TxMCS = 3; + pLinkInfo[0].RxMCS = 4; + + if (numLinks > 1) + { + // For Mlo connections, set the link ID for the first link to 1 + pLinkInfo[0].LinkID = 1; + + pLinkInfo[1].LinkID = 2; + RtlCopyMemory(&pLinkInfo[1].LocalLinkMACAddress, &m_LocalLinkAddresses[1], sizeof(DOT11_MAC_ADDRESS)); + RtlCopyMemory(&pLinkInfo[1].PeerLinkMACAddress, &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS)); + pLinkInfo[1].ChannelNumber = 36; + pLinkInfo[1].BandId = WDI_BAND_ID_5000; + pLinkInfo[1].RSSI = -30; + pLinkInfo[1].Bandwidth = 160; + pLinkInfo[1].TxMCS = 8; + pLinkInfo[1].RxMCS = 9; + } + + linkStateChangeParameters.LinkInfo.pElements = pLinkInfo; + linkStateChangeParameters.LinkInfo.ElementCount = numLinks > 1 ? 2 : 1; + + ntStatus = GenerateWdiIndicationLinkStateChangeFromIhv(&linkStateChangeParameters, 0, &pDeviceContext->TlvContext, &cbOutput, &pOutput); + if (STATUS_SUCCESS == ntStatus) + { + WifiIhvSendUnsolicitedIndicationToOs(m_Device, pWdiHeader, WDI_INDICATION_LINK_STATE_CHANGE, pOutput, cbOutput); + FreeGenerated(pOutput); + } + else + { + WFCError("Failed to generate WDI_INDICATION_LINK_STATE_CHANGE - 0x%08x\n", ntStatus); + } + + return ntStatus; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvPerformAssociation( + const struct ArrayOfElements<WDI_CONNECT_BSS_ENTRY_CONTAINER>* pPreferredBSSEntryList, + const struct ArrayOfElements<WDI_AUTH_ALGORITHM>* pAuthenticationAlgorithms, + const PWDI_MESSAGE_HEADER pWdiHeader) +{ + + ULONG bssIndex = 0; + ULONG connectEntry = ConnectEntryId_MAX; + NTSTATUS ntStatus = STATUS_SUCCESS; + UINT32 NewConnectEntryId = 0; // Disconnected State + WDI_AUTH_ALGORITHM NewAuthAlgo = pAuthenticationAlgorithms->pElements[0]; + UCHAR pucData[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10 }; + + PWIFI_IHV_DEVICE_CONTEXT pDeviceContext = WifiGetIhvDeviceContext(m_Device); + + ULONG assocStatus = WDI_ASSOC_STATUS_SUCCESS; + + do + { + // We search for the BSSID pattern to figure out what AP we are trying to connect to + for (bssIndex = 0; bssIndex < pPreferredBSSEntryList->ElementCount; bssIndex++) + { + for (connectEntry = 1; connectEntry < ConnectEntryId_MAX; connectEntry++) + { + if (RtlCompareMemory( + pPreferredBSSEntryList->pElements[bssIndex].BSSID.Address, + g_ConnectEntries[connectEntry].pMacAddress, + sizeof(DOT11_MAC_ADDRESS)) == sizeof(DOT11_MAC_ADDRESS)) + { + PUCHAR pAssociationResult = g_ConnectEntries[connectEntry].pTlvAssociationResult; + + NewConnectEntryId = connectEntry; + m_LastConnectTransactionId = pWdiHeader->TransactionId; +#ifdef NETV_SUPPORT_TX_DEMUXING + // add peer on datapath + WifiAdapterAddPeer(pDeviceContext->netAdapters[pWdiHeader->PortId], + reinterpret_cast<NET_EUI48_ADDRESS*>(g_ConnectEntries[connectEntry].pMacAddress)); +#endif // NETV_SUPPORT_TX_DEMUXING +#ifdef WIFI_IHV_HANDSHAKE + // Pretend to recieve M1 on datapath before, the association complete has made it up the control path. + RecieveDatapathFrame(0x33, sizeof(pucData), pucData); +#endif // WIFI_IHV_HANDSHAKE + + if (NewAuthAlgo == WDI_AUTH_ALGO_WPA3_SAE) + { + WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED_PARAMETERS SAEAuthParamsNeeded; + UINT8* pOutput = nullptr; + ULONG cbOutput = 0; + NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS; + + // + // Handle special case for WPA3-SAE + // Send the Indication to request additonal SAE params + // + g_dwSaeResendConfirmRequested = 0; + SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_COMMIT_REQUEST_PARAMS_NEEDED; + RtlCopyMemory( + SAEAuthParamsNeeded.BssId.Address, g_ConnectEntries[connectEntry].pMacAddress, sizeof(DOT11_MAC_ADDRESS)); + + ndisStatus = GenerateWdiIndicationSaeAuthParamsNeeded( + &SAEAuthParamsNeeded, 0, &pDeviceContext->TlvContext, &cbOutput, &pOutput); + if (ndisStatus == NDIS_STATUS_SUCCESS) + { + WFCInfo("[SAE] Indicating request for COMMIT_REQUEST_PARAMS_NEEDED ..."); + + WifiIhvSendUnsolicitedIndicationToOs(m_Device, pWdiHeader, WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED, pOutput, cbOutput); + + FreeGenerated(pOutput); + + break; + } + } + + // Get the assoc status + RtlCopyMemory(&assocStatus, &pAssociationResult[18], sizeof(ULONG)); + + // Send the association indication + WifiIhvSendUnsolicitedIndicationToOs( + m_Device, + pWdiHeader, + WDI_INDICATION_ASSOCIATION_RESULT, + g_ConnectEntries[connectEntry].pTlvAssociationResult, + g_ConnectEntries[connectEntry].TlvAssociationResultSize); + + break; + } + } + + // If we found a matching BSSID entry, we are done + if (connectEntry < ConnectEntryId_MAX) + { + break; + } + } + + } while (FALSE); + + if (WDI_ASSOC_STATUS_SUCCESS != assocStatus || 0 == NewConnectEntryId || bssIndex >= pPreferredBSSEntryList->ElementCount) + { + NewConnectEntryId = 0; // Disconnected State + NewAuthAlgo = WDI_AUTH_ALGO_80211_OPEN; + ntStatus = STATUS_UNSUCCESSFUL; + } + else + { + RtlCopyMemory(&m_ConnectedPeer, pPreferredBSSEntryList->pElements[bssIndex].BSSID.Address, sizeof(DOT11_MAC_ADDRESS)); + } + + m_LastConnectEntryId = NewConnectEntryId; + m_LastAuthAlgo = NewAuthAlgo; + + if (STATUS_SUCCESS == ntStatus && (WDI_AUTH_ALGO_WPA3_SAE != m_LastAuthAlgo)) + { + // Report link quality + ntStatus = WifiIhvSendLinkStateIndication(pWdiHeader, 2); + } + + return ntStatus; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvSetSaeAuthParams(const WDI_SET_SAE_AUTH_PARAMS_COMMAND& setSAEAuthParams, const PWDI_MESSAGE_HEADER pWdiHeader, UINT) +{ + //Since this is DIRECT OID, need to check the m_LastConnectTransactionId match + if (pWdiHeader->TransactionId != m_LastConnectTransactionId) + { + WFCError("WDI_SET_SAE_AUTH_PARAMS called with invalid TransactionId: %llu, expected: %llu\n", + pWdiHeader->TransactionId, m_LastConnectTransactionId); + return STATUS_INVALID_DEVICE_REQUEST; + } + + WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED_PARAMETERS SAEAuthParamsNeeded{}; + UINT8* pOutput = nullptr; + ULONG cbOutput = 0; + + // Commit frame when Status = 0: FiniteCyclicGroup + Scalar + Element + // Commit frame when Status = 76: FiniteCyclicGroup + AntiCloggingToken + WFCInfo("WDI_SET_SAE_AUTH_PARAMS called!!!\n"); + if (WDI_SAE_REQUEST_TYPE_COMMIT_PARAMS == setSAEAuthParams.SAERequestType) + { + WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS has Commit request for Tx, Setting CommitResponse for Rx\n"); + + SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_COMMIT_FRAME; + SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1; + + // + // Send reflection attack first + // + SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAECommitResponseReflection); + SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAECommitResponseReflection; + } + else if ( + (WDI_SAE_REQUEST_TYPE_FAILURE == setSAEAuthParams.SAERequestType) && + (WDI_SAE_STATUS_COMMIT_MESSAGE_REFLECTION_ATTACK_DETECTED == setSAEAuthParams.SAEStatus)) + { + WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS returned Reflection error -- Inidicate proper CommitResponse for Rx\n"); + + SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_FRAME; + SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1; + SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAECommitResponse); + SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAECommitResponse; + } + else if (WDI_SAE_REQUEST_TYPE_CONFIRM_PARAMS == setSAEAuthParams.SAERequestType) + { + WFCInfo("[SAE] WDI_SET_SAE_AUTH_PARAMS has Confirm request for Tx, Setting ConfirmResponse for Rx\n"); + + if (g_dwSaeResendConfirmRequested) + { + SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_FRAME; + SAEAuthParamsNeeded.Optional.SAECommitFrame_IsPresent = 1; + SAEAuthParamsNeeded.SAECommitFrame.ElementCount = sizeof(pucSAEConfirmResponse); + SAEAuthParamsNeeded.SAECommitFrame.pElements = pucSAEConfirmResponse; + } + else + { + g_dwSaeResendConfirmRequested = 1; + + SAEAuthParamsNeeded.SAEIndicationType = WDI_SAE_INDICATION_TYPE_CONFIRM_REQUEST_RESEND_REQUEST; + } + } + else + { + if (WDI_SAE_REQUEST_TYPE_FAILURE == setSAEAuthParams.SAERequestType) + { + WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has indicated error - %d\n", setSAEAuthParams.SAEStatus); + } + else if (WDI_SAE_REQUEST_TYPE_SUCCESS == setSAEAuthParams.SAERequestType) + { + WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has indicated SAE success - %d\n", setSAEAuthParams.SAEStatus); + } + else + { + WFCInfo("[SAE] OID_WDI_SET_SAE_AUTH_PARAMS has set INVALID Request type = %d\n", setSAEAuthParams.SAERequestType); + } + + // Send the association indication + // This assumes that the association result fields are in the right order + if (WDI_AUTH_ALGO_WPA3_SAE == m_LastAuthAlgo) + { + g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult[27] = (UCHAR)WDI_AUTH_ALGO_WPA3_SAE; + } + else + { + g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult[27] = (UCHAR)WDI_AUTH_ALGO_RSNA_PSK; + } + + WifiIhvSendUnsolicitedIndicationToOs( + m_Device, + pWdiHeader, + WDI_INDICATION_ASSOCIATION_RESULT, + g_ConnectEntries[m_LastConnectEntryId].pTlvAssociationResult, + g_ConnectEntries[m_LastConnectEntryId].TlvAssociationResultSize); + RtlCopyMemory(&m_ConnectedPeer, &g_ConnectEntries[m_LastConnectEntryId].pMacAddress, sizeof(DOT11_MAC_ADDRESS)); + + // Report link quality + WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(WifiIhvSendLinkStateIndication(pWdiHeader, 1), + "Failed WifiIhvSendLinkStateIndication"); + + // Complete the transaction to let the M4 hanlder WifiIhvGetPendingTransitionStatus know that association is complete + m_LastConnectTransactionId = 0; + +#ifdef WIFI_IHV_HANDSHAKE + // + // Receive M1 frame of 4-way handshake + // + RecieveDatapathFrame(0x33, sizeof(pucM1SaeFrame), pucM1SaeFrame); + + // + // Receive M3 frame of 4-way handshake + // + RecieveDatapathFrame(0x33, sizeof(pucM3SaeFrame), pucM3SaeFrame); +#endif + return STATUS_SUCCESS; + } + + RtlCopyMemory(SAEAuthParamsNeeded.BssId.Address, &g_ConnectEntries[m_LastConnectEntryId].pMacAddress, sizeof(DOT11_MAC_ADDRESS)); + + auto ndisStatus = + GenerateWdiIndicationSaeAuthParamsNeeded(&SAEAuthParamsNeeded, 0, m_TlvContext, &cbOutput, &pOutput); + if (ndisStatus == NDIS_STATUS_SUCCESS) + { + WifiIhvSendUnsolicitedIndicationToOs(m_Device, pWdiHeader, WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED, pOutput, cbOutput); + + FreeGenerated(pOutput); + } + else + { + WFCError("Failed to generate WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED - 0x%08x\n", ndisStatus); + } + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvDisconnect(const WDI_TASK_DISCONNECT_PARAMETERS&, const PWDI_MESSAGE_HEADER pWdiHeader, UINT) +{ + UCHAR s_TLV_Disassociation[] = + { + // WDI_TLV_ASSOCIATION_RESULT + 0xBC, 0x00, + 0x0A, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + // WDI_TLV Need Peer Cleanup Params + 0xb4, 0x00, + 0x01, 0x00, + + 0x00 + }; + WDI_ASSOC_STATUS DisassocStatus = WDI_ASSOC_STATUS_DISASSOCIATED_BY_HOST; + + RtlCopyMemory(&s_TLV_Disassociation[4], &m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS)); + RtlCopyMemory(&s_TLV_Disassociation[10], &DisassocStatus, sizeof(ULONG)); + + // Send the disassociation indication + WifiIhvSendUnsolicitedIndicationToOs(m_Device, pWdiHeader, WDI_INDICATION_DISASSOCIATION, s_TLV_Disassociation, sizeof(s_TLV_Disassociation)); + + m_LastConnectEntryId = 0; // Disconnected State + +#ifdef NETV_SUPPORT_TX_DEMUXING + WifiAdapterRemovePeer( + WifiGetIhvDeviceContext(m_Device)->netAdapters[pWdiHeader->PortId], + reinterpret_cast<NET_EUI48_ADDRESS*>(&m_ConnectedPeer)); +#endif + RtlZeroMemory(&m_ConnectedPeer, sizeof(DOT11_MAC_ADDRESS)); + + return STATUS_SUCCESS; +} + +// -------- WDI_GET_SUPPORTED_DEVICE_SERVICES (OID_WDI_GET_SUPPORTED_DEVICES) -------- +// Property GET: the request has no input (Inputs is empty). Builds the +// WDI_TLV_DEVICE_SERVICE_GUID_LIST result advertising GUID_OEM_SAMPLE_DEVICE_SERVICE and +// serializes it via the generated TLV generator, so the OS learns which device services +// this driver supports. +// OutBuffer receives the full WDI message (header + TLVs); BytesWritten = total length. +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvGetSupportedDeviceServices(const WDI_GET_SUPPORTED_DEVICE_SERVICES_INPUTS& Inputs, void* OutBuffer, ULONG OutBufferLen, ULONG& BytesWritten) +{ + UNREFERENCED_PARAMETER(Inputs); // GET request carries no input data + + BytesWritten = sizeof(WDI_MESSAGE_HEADER); + + if (OutBuffer == nullptr || OutBufferLen < sizeof(WDI_MESSAGE_HEADER)) + { + WFCError("GetSupportedDeviceServices: invalid out buffer (OutBufferLen=%u)", OutBufferLen); + return STATUS_INVALID_PARAMETER; + } + + // WDI_TLV_DEVICE_SERVICE_GUID_LIST: a list containing our single device service GUID. + // WDI_GUID_LIST_CONTAINER is ArrayOfElements<GUID>; SimpleAssign points it at our + // stack array (the generator copies the data while serializing the TLV). + GUID supportedServices[] = { GUID_OEM_SAMPLE_DEVICE_SERVICE }; + + WDI_GET_SUPPORTED_DEVICE_SERVICES_PARAMETERS results{}; + results.DeviceServiceGUIDList.SimpleAssign(supportedServices, ARRAYSIZE(supportedServices)); + + // Generate the TLV byte stream. ReservedHeaderLength reserves room for the + // WDI_MESSAGE_HEADER at the front of the produced buffer. + ULONG generatedLength = 0; + UINT8* pGenerated = nullptr; + + NDIS_STATUS genStatus = GenerateWdiGetSupportedDeviceServices( + &results, sizeof(WDI_MESSAGE_HEADER), m_TlvContext, &generatedLength, &pGenerated); + + NTSTATUS ntStatus = Wifi::ConvertNDISSTATUSToNTSTATUS(genStatus); + if (!NT_SUCCESS(ntStatus) || pGenerated == nullptr) + { + WFCError("GetSupportedDeviceServices: Generate failed, status=%!STATUS!", ntStatus); + return ntStatus; + } + + if (OutBufferLen < generatedLength) + { + WFCError("GetSupportedDeviceServices: out buffer too small (have=%u need=%u)", + OutBufferLen, generatedLength); + FreeGenerated(pGenerated); + return STATUS_BUFFER_TOO_SMALL; + } + + RtlCopyMemory(OutBuffer, pGenerated, generatedLength); + BytesWritten = generatedLength; + FreeGenerated(pGenerated); + + WFCInfo("GetSupportedDeviceServices: advertised %u device service(s), %u bytes", + ARRAYSIZE(supportedServices), BytesWritten); + return STATUS_SUCCESS; +} + +// -------- OEM Device Service Command (OID_WDI_DEVICE_SERVICE_COMMAND) -------- +// Reads the request data blob (WDI_TLV_DEVICE_SERVICE_PARAMS_DATA_BLOB) parsed into +// Inputs.Params, expects "Hello, My Driver", and returns "Nice to meet you, My OEM" +// as the response data blob, serialized via the generated TLV generator. +// OutBuffer receives the full WDI message (header + TLVs); BytesWritten = total length. +_Use_decl_annotations_ +NTSTATUS WifiHAL::WifiIhvDeviceServiceCommand(const WDI_DEVICE_SERVICE_COMMAND_INPUTS& Inputs, void* OutBuffer, ULONG OutBufferLen, ULONG& BytesWritten) +{ + BytesWritten = sizeof(WDI_MESSAGE_HEADER); + + if (OutBuffer == nullptr || OutBufferLen < sizeof(WDI_MESSAGE_HEADER)) + { + WFCError("OEM device service: invalid out buffer (OutBufferLen=%u)", OutBufferLen); + return STATUS_INVALID_PARAMETER; + } + + // Log the request data blob ("Hello, My Driver"), if present. + if (Inputs.Optional.Params_IsPresent && + Inputs.Params.ElementCount > 0 && + Inputs.Params.pElements[0].ElementCount > 0 && + Inputs.Params.pElements[0].pElements != nullptr) + { + WFCInfo("OEM device service: opcode=0x%08X, received %u-byte data blob: %hs", + Inputs.Opcode, + Inputs.Params.pElements[0].ElementCount, + reinterpret_cast<const char*>(Inputs.Params.pElements[0].pElements)); + } + else + { + WFCInfo("OEM device service: opcode=0x%08X, no input data blob", Inputs.Opcode); + } + + // Build the response data blob ("Nice to meet you, My OEM"), including the null terminator. + // SimpleAssign points the blob at this buffer (no copy); the generator copies the bytes + // while serializing, and the buffer outlives that call. + UINT8 responseBytes[] = OEM_DEVICE_SERVICE_RESPONSE_STRING; + + WDI_BYTE_BLOB responseBlob{}; + responseBlob.SimpleAssign(responseBytes, static_cast<UINT32>(sizeof(responseBytes))); + + WDI_DEVICE_SERVICE_COMMAND_PARAMETERS params{}; + params.Optional.Params_IsPresent = TRUE; + params.Params.SimpleAssign(&responseBlob, 1); + + // Serialize WDI_TLV_DEVICE_SERVICE_PARAMS_DATA_BLOB into the response message. + ULONG generatedLength = 0; + UINT8* pGenerated = nullptr; + + NDIS_STATUS genStatus = GenerateWdiDeviceServiceCommand( + ¶ms, sizeof(WDI_MESSAGE_HEADER), m_TlvContext, &generatedLength, &pGenerated); + + NTSTATUS ntStatus = Wifi::ConvertNDISSTATUSToNTSTATUS(genStatus); + if (!NT_SUCCESS(ntStatus) || pGenerated == nullptr) + { + WFCError("OEM device service: Generate failed, status=%!STATUS!", ntStatus); + return ntStatus; + } + + if (OutBufferLen < generatedLength) + { + WFCError("OEM device service: out buffer too small (have=%u need=%u)", + OutBufferLen, generatedLength); + FreeGenerated(pGenerated); + return STATUS_BUFFER_TOO_SMALL; + } + + RtlCopyMemory(OutBuffer, pGenerated, generatedLength); + BytesWritten = generatedLength; + FreeGenerated(pGenerated); + + WFCInfo("OEM device service: responded with \"%hs\" (%u bytes)", + reinterpret_cast<const char*>(responseBytes), BytesWritten); + return STATUS_SUCCESS; +} diff --git a/network/wlan/wificx/drivercode/wifihal.h b/network/wlan/wificx/drivercode/wifihal.h new file mode 100644 index 00000000..f776f425 --- /dev/null +++ b/network/wlan/wificx/drivercode/wifihal.h @@ -0,0 +1,63 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +// The class for Wifi IHV device's HAL functionalities +class WifiHAL +{ +public: + static NTSTATUS _Create(_In_ WDFDEVICE Device); + static void _OnCleanup(_In_ WDFOBJECT Object); + + // Default ctor so context memory can be zeroed by WDF without placement new + WifiHAL() = default; + + // Initialization routine replacing the previous parameterized ctor usage + void Initialize(_In_ WDFDEVICE Device, _In_ PCTLV_CONTEXT TlvContext); + + // Wifi request M3 working condition verification function + NTSTATUS WifiIhvIsDeviceReadyForRequest(); + + // Wifi request pending transition status check function + // for example, during SAE authentication, the connect request is pending until SAE exchange is complete + NTSTATUS WifiIhvGetPendingTransitionStatus(); + + NTSTATUS WifiIhvSetDeviceCapabilities(); + NTSTATUS WifiIhvReset(_In_ const WDI_TASK_DOT11_RESET_PARAMETERS& ResetParameters, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + NTSTATUS WifiIhvSetRadioState(_In_ const WDI_SET_RADIO_STATE_PARAMETERS& RadioState, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + NTSTATUS WifiIhvScan(_In_ const WDI_SCAN_PARAMETERS& ScanParameters, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + NTSTATUS WifiIhvConnect(_In_ const WDI_TASK_CONNECT_PARAMETERS& ConnectParameters, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + NTSTATUS WifiIhvSetSaeAuthParams(_In_ const WDI_SET_SAE_AUTH_PARAMS_COMMAND& setSAEAuthParams, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + NTSTATUS WifiIhvDisconnect(_In_ const WDI_TASK_DISCONNECT_PARAMETERS& disconnectParameters, _In_ const PWDI_MESSAGE_HEADER pWdiHeader, _In_ UINT BytesWritten); + + // Device service property handlers (OID_WDI_GET_SUPPORTED_DEVICES / OID_WDI_DEVICE_SERVICE_COMMAND). + // Match the PropertyTransitionTraits handler shape: (const parsed input&, out-buffer, + // out-buffer length, bytesWritten&). The handler serializes the response TLV stream into + // OutBuffer and reports the number of bytes written; the dispatch layer completes the request. + NTSTATUS WifiIhvGetSupportedDeviceServices( + _In_ const WDI_GET_SUPPORTED_DEVICE_SERVICES_INPUTS& Inputs, + _Out_writes_bytes_to_(OutBufferLen, BytesWritten) void* OutBuffer, + _In_ ULONG OutBufferLen, + _Out_ ULONG& BytesWritten); + NTSTATUS WifiIhvDeviceServiceCommand( + _In_ const WDI_DEVICE_SERVICE_COMMAND_INPUTS& Inputs, + _Out_writes_bytes_to_(OutBufferLen, BytesWritten) void* OutBuffer, + _In_ ULONG OutBufferLen, + _Out_ ULONG& BytesWritten); +private: + NTSTATUS WifiIhvPerformAssociation(_In_ const struct ArrayOfElements<WDI_CONNECT_BSS_ENTRY_CONTAINER>* pPreferredBSSEntryList, _In_ const struct ArrayOfElements<WDI_AUTH_ALGORITHM>* pAuthenticationAlgorithms, _In_ const PWDI_MESSAGE_HEADER pWdiHeader); + NTSTATUS WifiIhvSendLinkStateIndication(_In_ const PWDI_MESSAGE_HEADER pWdiHeader, ULONG numLinks); + + WDFDEVICE m_Device{}; + PCTLV_CONTEXT m_TlvContext{}; + + UCHAR m_CurrentRadioState{}; + UINT32 m_LastConnectEntryId{}; + UINT32 m_LastConnectTransactionId{}; + WDI_AUTH_ALGORITHM m_LastAuthAlgo{}; + DOT11_MAC_ADDRESS m_ConnectedPeer{}; + + // Removed const so we can initialize without running a constructor via placement new + WDI_MAC_ADDRESS m_LocalLinkAddresses[2]; + ULONG m_SupportedBands; +}; +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WifiHAL, GetWifiHalFromHandle); diff --git a/network/wlan/wificx/drivercode/wifihaltestdata.h b/network/wlan/wificx/drivercode/wifihaltestdata.h new file mode 100644 index 00000000..7ded0f2b --- /dev/null +++ b/network/wlan/wificx/drivercode/wifihaltestdata.h @@ -0,0 +1,8290 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once + +#define TESTMP_BAND_IHV 0x00000010 + +// clang-format on + +#define ConnectEntryId_MAX ARRAYSIZE(g_ConnectEntries) + +// +//=============================================================================== +// Set alternate local addresses based on simulation parameters +//=============================================================================== +// +UCHAR s_ArubaSimLocalAddress[] = {0xd4, 0x6a, 0x6a, 0x52, 0x18, 0x07}; // For Wpa3SuiteB - Aruba +UCHAR g_IntelSimLocalAddress[] = {0x34, 0x13, 0xe8, 0xb3, 0x14, 0x4c}; // For Wpa3SuiteB - Intel +UCHAR g_SaeSimLocalAddress[] = {0x9c, 0xda, 0x3e, 0xf2, 0x7d, 0xd5}; // For Wpa3Sae + +#ifdef WPA3_ARUBA_SIM +PUCHAR g_AlternateLocalAddress = s_ArubaSimLocalAddress; +#elif WPA3_INTEL_SIM +PUCHAR g_AlternateLocalAddress = g_IntelSimLocalAddress; +#elif WPA3_SAE +PUCHAR g_AlternateLocalAddress = g_SaeSimLocalAddress; +#else +PUCHAR g_AlternateLocalAddress = NULL; +#endif + +// clang-format off + +// +//=============================================================================== +// + +UCHAR s_DeviceServiceTestBlob[] = +{ + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa +}; + +// +//=============================================================================== +// + +UCHAR s_TLV_AssociationParametersRequestedType[] = +{ + // WDI_TLV_ASSOCIATION_PARAMETERS_REQUESTED_TYPE + 0xBB, 0x00, + 0x02, 0x00, + 0x9F, 0x00 // PMKID +}; + +UCHAR s_TLV_RoamingNeededIndication[] = +{ + // WDI_TLV_ROAMING_NEEDED_PARAMETERS + 0x55, 0x00, + 0x04, 0x00, + 0x0a, 0x00, 0x00, 0x00 +}; + +UCHAR s_TLV_NeighborReport[] = +{ + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_ACTION_FRAME_BODY + 0xBE, 0x00, + 0x14, 0x00, + 0x05, // Category = Radio Measurement + 0x05, // Action = Neighbor Report Response + 0x01, // Dialog Token + 0x34, // Element ID = Neighbor Report + 0x0F, // Length + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, // BSSID + 0x00, 0x00, 0x00, 0x00, // BSSID Information + 0x00, // Operating class + 0x06, // Channel Number + 0x00, // PHY Type + 0x00, 0x00, // Optional IEs +}; + +// +//=============================================================================== +// + +// +//=============================================================================== +// BSs entries +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr = {0x00, 0x20, 0x30, 0x40, 0x50, 0x60}; + +UCHAR s_TLV_BSS_Entry_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x63, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x35, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'W', 'F', 'C', '_', 'O', 'P', 'E', 'N', // SSID + 0x01, 0x04, // Supported Rates + 0x02, 0x04, 0x0B, 0x16, + 0x03, 0x01, // DSSS Parameter + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x46, 0x05, // RM Enabled Capabilities + 0x02, 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x07, // Vendor specific - MBO-OCE IE + 0x50, 0x6F, 0x9A, // WFA OUI + 0x16, // MBO-OCE IE OUI Type + 0x01, // Attribute ID - AP capability + 0x01, // Attrib length + 0x00, // Not cellular data aware + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_SuccessOpenAssociationResult[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD7, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x30, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, + 'W', 'F', 'C', '_', 'O', 'P', 'E', 'N', // SSID + 0x01, 0x08, // Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x21, 0x02, // Power Capability + 0x07, 0x12, + 0x24, 0x02, // Supported Channels + 0x01, 0x0B, + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x07, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, //Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x32, 0x04, //Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x18, //WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'W', 'F', 'C', '_', 'O', 'P', 'E', 'N', // SSID + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_ETHERTYPE_ENCAP_TABLE (optional) + // 0x00, 0x00, + // 0x04, 0x00, + // 0x00, 0x00, 0x00, 0x00 + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, + +}; + + +UCHAR s_TLV_OpenDisassociation[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0xBC, 0x00, + 0x0A, 0x00, + 0x00, 0x20, 0x30, 0x40, 0x50, 0x60, + 0x01, 0x00, 0x00, 0x00, + + // WDI_TLV Need Peer Cleanup Params + 0xb4, 0x00, + 0x01, 0x00, + 0x00 +}; + +WDI_MAC_ADDRESS s_Connect_Addr_2_Open = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE2}; + +UCHAR s_TLV_BSS_Entry_2_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x59, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE2, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x26, 0x00, + 0x44, 0x55, 0x66, 0x77, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', + 0x03, 0x01, // DSSS Parameter + 0x01, + 0x01, 0x04, // Supported Rates + 0x02, 0x04, 0x0B, 0x16, + 0x46, 0x05, // RM Enabled Capabilities + 0x02, 0x00, 0x00, 0x00, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x28, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // Band ID + +}; + +UCHAR s_TLV_Success_AssociationResult_2_Open[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD7, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE2, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x30, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', + 0x01, 0x08, // Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x21, 0x02, // Power Capability + 0x07, 0x12, + 0x24, 0x02, // Supported Channels + 0x01, 0x0B, + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x07, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, // Capability + 0x00, 0x00, // Status + 0x01, 0xC0, // Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x18, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x25, 0x00, + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', + 0x01, 0x04, + 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, // DSSS Parameter + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + + // WDI_TLV_ETHERTYPE_ENCAP_TABLE (optional) + // 0x00, 0x00, + // 0x04, 0x00, + // 0x00, 0x00, 0x00, 0x00 + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + +// +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_3_WEP = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE3}; + +UCHAR s_TLV_BSS_Entry_3_WEP [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x52, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE3, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x1f, 0x00, + 0x44, 0x55, 0x66, 0x77, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x10, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'W', 'E', 'P', + 0x03, 0x01, 0x01, // DSSS Parameter (Offset: 42) + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x3C, 0x00, 0x00, 0x00, // Link Quality (Offset: 57) + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel (Offset: 64) + 0x01, 0x00, 0x00, 0x00, // Band ID + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00 +}; + + +UCHAR s_TLV_Success_AssociationResult_3_WEP[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD9, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE3, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x32, 0x00, + 0x10, 0x04, // Capability + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'W', 'E', 'P', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x01, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x07, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x10, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'W', 'E', 'P', + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_ETHERTYPE_ENCAP_TABLE (optional) + // 0x00, 0x00, + // 0x04, 0x00, + // 0x00, 0x00, 0x00, 0x00 + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + + +// +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_4_RSNA_CCMP = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE4}; + +#define WFA_TEST_MIN_RSN_IE 1 + +UCHAR s_TLV_BSS_Entry_4_RSNA_CCMP [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type +#ifdef WFA_TEST_MIN_RSN_IE + 0x79, 0x00, //Len +#else + 0x8B, 0x00, //Len +#endif // WFA_TEST_MIN_RSN_IE + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE4, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, +#ifdef WFA_TEST_MIN_RSN_IE + 0x46, 0x00, +#else + 0x58, 0x00, +#endif // WFA_TEST_MIN_RSN_IE + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'E', 'C', 'U', 'R', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved +#ifdef WFA_TEST_MIN_RSN_IE + 0x30, 0x02, + 0x01, 0x00, +#else + 0x30, 0x14, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher -- CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher -- CCMP + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite -- RSNA_PSK + 0x00, 0x00, // RSN Capability +#endif // WFA_TEST_MIN_RSN_IE + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_4_RSNA_CCMP[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x22, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE4, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x48, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'E', 'C', 'U', 'R', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x01, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x14, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x02, 0x00, 0x00, // RSN + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x58, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'E', 'C', 'U', 'R', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x14, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x02, 0x00, 0x00, // RSN + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + + +// +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_5_IHV = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5}; + +UCHAR s_TLV_BSS_Entry_5_IHV [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x52, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x1f, 0x00, + 0x44, 0x55, 0x66, 0x77, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x10, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'I', 'H', 'V', + 0x03, 0x01, 0x01, // DSSS Parameter + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x3C, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x24, 0x00, 0x00, 0x00, // Channel = 36 + 0x08, 0x00, 0x00, 0x00, // Band ID = Custom +// 0x02, 0x00, 0x00, 0x00, // Band ID + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00 +}; + + +UCHAR s_TLV_Success_AssociationResult_5_IHV[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD9, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x02, 0x00, 0x00, 0x80, //AuthAlgorithm = Custom + 0x01, 0x00, 0x00, 0x80, //UnicastCipherAlgorithm + 0x01, 0x00, 0x00, 0x80, //MulticastDataCipherAlgorithm + 0x01, 0x00, 0x00, 0x80, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x80, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x32, 0x00, + 0x10, 0x04, // Capability + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'I', 'H', 'V', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x24, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x07, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x10, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', '_', 'I', 'H', 'V', + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_ETHERTYPE_ENCAP_TABLE (optional) + // 0x00, 0x00, + // 0x04, 0x00, + // 0x00, 0x00, 0x00, 0x00 + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x02, 0x00, 0x00, 0x80, // Phy = IHV Phy 2 + +}; + + +UCHAR s_TLV_IhvRequestComplete[] = +{ + // WDI_TLV_IHV_DATA + 0xBD, 0x00, + 0x0A, 0x00, + + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0x00, 0x00, 0x01 +}; + + +UCHAR s_TLV_IhvIndication[] = +{ + // WDI_TLV_IHV_DATA + 0xBD, 0x00, + 0x30, 0x00, + + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE5 +}; + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_6_FT_CCMP = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE6}; + +UCHAR s_TLV_BSS_Entry_6_FT_CCMP [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xEA, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE6, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xB7, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x07, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', // WDI__FT + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x03, 0x01, // DSS Parameters + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x07, 0x06, // Country + 0x55, 0x53, 0x20, 0x01, 0x0B, 0x1E, + 0x0B, 0x05, + 0x00, 0x00, 0x53, 0x8D, 0x5B, + 0x2A, 0x01, + 0x00, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x03, // AKM Suite + 0x28, 0x00, // RSN Capability + 0x32, 0x01, + 0x6C, + 0x36, 0x03, // MDID IE + 0x0B, 0x47, // MDID + 0x00, // FT Capability and Policy + 0x85, 0x1E, + 0x00, 0x00, 0x8F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0x59, 0x00, 0x41, 0x50, 0x30, 0x30, 0x31, 0x34, + 0x2E, 0x36, 0x39, 0x34, 0x30, 0x2E, 0x38, 0x35, 0x32, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x96, 0x06, + 0x00, 0x40, 0x96, 0x00, 0x0B, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x06, + 0x00, 0x40, 0x96, 0x01, 0x01, 0x04, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x03, 0x05, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x0B, 0x09, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x14, 0x01, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x4A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_6_FT_CCMP[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0C, 0x02, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE6, + + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x06, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x3E, 0x00, + 0x31, 0x04, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x07, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', // WDI__FT + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher -- CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher -- CCMP + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x03, // AKM Suite -- FT + 0x0C, 0x00, // RSN Capability + 0x32, 0x01, // Extended Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x0B, 0x47, // MDID + 0x00, // FT Capability and Policy + 0xDD, 0x07, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0xC5, 0x00, + 0x31, 0x04, // Capability + 0x00, 0x00, // Status + 0x01, 0xC0, // Association ID + 0x01, 0x08, // Supported Rates + 0x96, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x30, 0x26, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher -- CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher -- CCMP + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x03, // AKM Suite -- FT + 0x28, 0x00, // RSN Capability + 0x01, 0x00, // PMKID Count -- PMKR1Name + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //PMKID + 0x32, 0x01, // Extended Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x0B, 0x47, // MDID + 0x00, // FT Capability and Policy + 0x37, 0x69, // FTE IE + 0x00, 0x00, // MIC Control - 0 => no MIC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //MIC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //ANonce + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //SNonce + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x06, // R1KH-ID + 0xB4, 0xC7, 0x99, 0x8A, 0xB6, 0x30, + 0x03, 0x0D, // R0KH-ID + 'a', 'p', '8', '1', '3', '2', '-', '7', '3', '4', 'E', 'B', '0', + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xB7, 0x00, + 0xDD, 0x50, 0x3D, 0xF7, 0xE2, 0x01, 0x00, 0x00, // Supported Rates + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x07, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', // WDI__FT + 0x01, 0x08, + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x03, 0x01, // DSS Parameters + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x07, 0x06, // Country + 0x55, 0x53, 0x20, 0x01, 0x0B, 0x1E, + 0x0B, 0x05, + 0x00, 0x00, 0x6E, 0x8D, 0x5B, + 0x2A, 0x01, // ERP + 0x00, + 0x30, 0x14, // RSN + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise cipher count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise cipher + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x03, // AKM Suite + 0x0C, 0x00, // RSN Capability + 0x32, 0x01, // Extended Supported Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x0B, 0x47, // MDID + 0x00, // FT Capability and Policy + 0x85, 0x1E, + 0x03, 0x00, 0x8F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0x59, 0x00, 0x41, 0x50, 0x30, 0x30, 0x31, 0x34, + 0x2E, 0x36, 0x39, 0x34, 0x30, 0x2E, 0x38, 0x31, 0x65, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x96, 0x06, + 0x00, 0x40, 0x96, 0x00, 0x0E, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x06, + 0x00, 0x40, 0x96, 0x01, 0x01, 0x04, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x03, 0x05, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x0B, 0x09, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x14, 0x01, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00 +}; + + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_7_FT_PSK_CCMP = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE7}; + +UCHAR s_TLV_BSS_Entry_7_FT_PSK_CCMP [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xED, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE7, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xBA, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', 'P', 'S', 'K', // WDI__FTPSK + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x03, 0x01, // DSS Parameters + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x07, 0x06, // Country + 0x55, 0x53, 0x20, 0x01, 0x0B, 0x1E, + 0x0B, 0x05, + 0x00, 0x00, 0x53, 0x8D, 0x5B, + 0x2A, 0x01, + 0x00, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x04, // AKM Suite + 0x28, 0x00, // RSN Capability + 0x32, 0x01, + 0x6C, + 0x36, 0x03, // MDID IE + 0x12, 0x34, // MDID + 0x80, // FT Capability and Policy + 0x85, 0x1E, + 0x00, 0x00, 0x8F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0x59, 0x00, 0x41, 0x50, 0x30, 0x30, 0x31, 0x34, + 0x2E, 0x36, 0x39, 0x34, 0x30, 0x2E, 0x38, 0x35, 0x32, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x96, 0x06, + 0x00, 0x40, 0x96, 0x00, 0x0B, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x06, + 0x00, 0x40, 0x96, 0x01, 0x01, 0x04, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x03, 0x05, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x0B, 0x09, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x14, 0x01, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x4A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_7_FT_PSK_CCMP[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0C, 0x02, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE7, + + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x41, 0x00, + 0x31, 0x04, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', 'P', 'S', 'K', // WDI__FTPSK + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x30, 0x14, // RSN IE + 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, 0xAC, 0x04, 0x01, 0x00, 0x00, 0x0F, + 0xAC, 0x01, 0x00, 0x00, + 0x32, 0x01, // Extended Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x12, 0x34, // MDID + 0x80, // FT Capability and Policy + 0xDD, 0x07, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0xBF, 0x00, + 0x31, 0x04, // Capability + 0x00, 0x00, // Status + 0x01, 0xC0, // Association ID + 0x01, 0x08, // Supported Rates + 0x96, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x30, 0x26, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher -- CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher -- CCMP + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x04, // AKM Suite -- FT-PSK + 0x28, 0x00, // RSN Capability + 0x01, 0x00, // PMKID Count -- PMKR1Name + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //PMKID + 0x32, 0x01, // Extended Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x12, 0x34, // MDID + 0x80, // FT Capability and Policy + 0x37, 0x63, // FTE IE + 0x00, 0x02, // MIC Control + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //MIC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //ANonce + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //SNonce + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x06, // R1KH-ID + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE7, + 0x03, 0x07, // R0KH-ID + 'x', '@', 'y', '.', 'c', 'o', 'm', + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xBA, 0x00, + 0xDD, 0x50, 0x3D, 0xF7, 0xE2, 0x01, 0x00, 0x00, // Supported Rates + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', '_', 'F', 'T', 'P', 'S', 'K', // WDI__FTPSK + 0x01, 0x08, + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x03, 0x01, // DSS Parameters + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x07, 0x06, // Country + 0x55, 0x53, 0x20, 0x01, 0x0B, 0x1E, + 0x0B, 0x05, + 0x00, 0x00, 0x6E, 0x8D, 0x5B, + 0x2A, 0x01, // ERP + 0x00, + 0x30, 0x14, // RSN + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise cipher count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise cipher + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x04, // AKM Suite + 0x28, 0x00, // RSN Capability + 0x32, 0x01, // Extended Supported Rates + 0x6C, + 0x36, 0x03, // MDID IE + 0x12, 0x34, // MDID + 0x80, // FT Capability and Policy + 0x85, 0x1E, + 0x03, 0x00, 0x8F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0x59, 0x00, 0x41, 0x50, 0x30, 0x30, 0x31, 0x34, + 0x2E, 0x36, 0x39, 0x34, 0x30, 0x2E, 0x38, 0x31, 0x65, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x96, 0x06, + 0x00, 0x40, 0x96, 0x00, 0x0E, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x06, + 0x00, 0x40, 0x96, 0x01, 0x01, 0x04, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x03, 0x05, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x0B, 0x09, + 0xDD, 0x05, + 0x00, 0x40, 0x96, 0x14, 0x01, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x06, 0x00, 0x00, 0x00 +}; + + +// +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_8_Hidden = {0x00, 0xA0, 0xB0, 0xC0, 0xD0,0xE8}; + +UCHAR s_TLV_BSS_Entry_Beacon_8_Hidden [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x52, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE8, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x24, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x00, // SSID + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x46, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, // RM Enabled Capabilities + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_BSS_Entry_ProbeResponse_8_Hidden [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x5a, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE8, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x2C, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'H', 'I', 'D', 'E', + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x46, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, // RM Enabled Capabilities + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // Band ID +}; + + +UCHAR s_TLV_Success_AssociationResult_8_Hidden[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD7, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE8, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x30, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'H', 'I', 'D', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x01, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x07, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, // SSID + 'W', 'D', 'I', '_', 'H', 'I', 'D', 'E', + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_ETHERTYPE_ENCAP_TABLE (optional) + // 0x00, 0x00, + // 0x04, 0x00, + // 0x00, 0x00, 0x00, 0x00 + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + + +//=============================================================================== +// +// 11ad +// +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_9_11ad_PSK = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9}; + +UCHAR s_TLV_BSS_Entry_9_11ad_Beacon_PSK [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x3F, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x0C, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x31, 0x04, // Capability + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_9_11ad_Beacon_Dmg_PSK [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x47, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x14, 0x00, // For WiFi Beacon + // DMG Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x00, 0x0c, 0x38, // 3 - Sector Sweep (9.5.1) + 0x64, 0x00, // 2 - Beacon Interval (9.4.1.3) + 0xc0, 0x7c, 0x18, 0x08, 0x20, 0x18, // 6 - Beacon Interval Control (Fig 9-60) + 0x07, // 1 - DMG Parameters (9.4.1.47) + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_9_11ad_ProbeResponse_PSK [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xCB, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x98, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x31, 0x04, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_9_11ad_ProbeResponse_Dmg_PSK [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xCB, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x98, 0x00, // For WiFi Beacon + // Dmg + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x17, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_9_11ad_PSK [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x96, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x08, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x08, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x65, 0x00, + 0x31, 0x04, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x94, 11, + 0x04, 0xCE, 0x14, 0x0A, 0x3B, 0x61, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x47, 0x00, + 0x17, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x94, 0x11, // DMG Capabilities + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, // STA address + 0x03, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x98, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +UCHAR s_TLV_Success_AssociationResult_9_11ad_Dmg_PSK [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x96, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xE9, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x08, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x08, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x65, 0x00, + 0x05, 0x00, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x94, 11, + 0x04, 0xCE, 0x14, 0x0A, 0x3B, 0x61, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x47, 0x00, + 0x17, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x94, 0x11, // DMG Capabilities + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, // STA address + 0x03, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x98, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_10_11ad_1x = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA}; + +UCHAR s_TLV_BSS_Entry_10_11ad_Beacon_1x [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x3F, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x0C, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x31, 0x04, // Capability + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_10_11ad_Beacon_Dmg_1x [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x47, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x14, 0x00, // For WiFi Beacon + // DMG Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x00, 0x0c, 0x38, // 3 - Sector Sweep (9.5.1) + 0x64, 0x00, // 2 - Beacon Interval (9.4.1.3) + 0xc0, 0x7c, 0x18, 0x08, 0x20, 0x18, // 6 - Beacon Interval Control (Fig 9-60) + 0x07, // 1 - DMG Parameters (9.4.1.47) + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_10_11ad_ProbeResponse_1x [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xCB, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x98, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x31, 0x04, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', '1', 'x', // WDI_ad_1x + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_10_11ad_ProbeResponse_Dmg_1x [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xCB, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x98, 0x00, // For WiFi Beacon + // Dmg + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x17, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', '1', 'x', // WDI_ad_1x + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_10_11ad_1x [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x96, 0x01, + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x08, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x08, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x65, 0x00, + 0x31, 0x04, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', '1', 'x', // WDI_ad_1x + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x94, 11, + 0x04, 0xCE, 0x14, 0x0A, 0x3B, 0x61, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x47, 0x00, + 0x17, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x94, 0x11, // DMG Capabilities + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, // STA address + 0x03, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x98, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +UCHAR s_TLV_Success_AssociationResult_10_11ad_Dmg_1x [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x96, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEA, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x08, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x08, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x01, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x65, 0x00, + 0x05, 0x00, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x01, 0x08, // Supported Rates + 0x0C, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, + + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x94, 11, + 0x04, 0xCE, 0x14, 0x0A, 0x3B, 0x61, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x47, 0x00, + 0x17, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x94, 0x11, // DMG Capabilities + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, // STA address + 0x03, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x98, 0x00, + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', 'P', 'S', 'K', // WDI_adPSK + 0x03, 0x01, // DSS Parameters + 0x02, + 0x30, 0x14, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x08, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x01, // AKM Suite + 0x00, 0x00, // RSN Capability + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0x34, 0x6B, 0x01, 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + 0xDD, 0x21, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_11_11ad_Open = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB}; + +UCHAR s_TLV_BSS_Entry_11_11ad_Beacon_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x3F, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x0C, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x05, 0x00, // Capability + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_11_11ad_Beacon_Dmg_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x47, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_BEACON_FRAME (8.3.3.2, Table 8-33a) + 0x0A, 0x00, + 0x05, 0x00, // For WiFi Beacon + // DMG Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x00, 0x0c, 0x38, // 3 - Sector Sweep (9.5.1) + 0x64, 0x00, // 2 - Beacon Interval (9.4.1.3) + 0xc0, 0x7c, 0x18, 0x08, 0x20, 0x18, // 6 - Beacon Interval Control (Fig 9-60) + 0x07, // 1 - DMG Parameters (9.4.1.47) + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_11_11ad_ProbeResponse_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC9, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x96, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x05, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x03, 0x01, // DSS Parameters + 0x02, + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x00, // AID + 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x28, + 0xDD, 0x27, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, 0x07, 0x00, 0x02, 0x00, 0x01, 0x00, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_BSS_Entry_11_11ad_ProbeResponse_Dmg_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC9, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_PROBE_RESPONSE_FRAME (8.3.3.2, Table 8-33a) + 0x09, 0x00, + 0x96, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x05, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x03, 0x01, // DSS Parameters + 0x02, + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x00, // AID + 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x28, + 0xDD, 0x27, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, 0x07, 0x00, 0x02, 0x00, 0x01, 0x00, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xC1, 0xFF, 0xFF, 0xFF, // RSSI + 0x64, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x03, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_11_11ad_Open [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x71, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x36, 0x00, + 0x05, 0x00, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x2E, 0x01, + 0x08, + 0x94, 11, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x00, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0x49, 0x2D, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x53, 0x00, + 0x07, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, // DMG Capabilities + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x02, // AID + 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x2C, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x96, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x05, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x03, 0x01, // DSS Parameters + 0x02, + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x28, + 0xDD, 0x27, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, 0x07, 0x00, 0x02, 0x00, 0x01, 0x00, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +UCHAR s_TLV_Success_AssociationResult_11_11ad_Dmg_Open [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x71, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm -- RSNA_PSK + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x03, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x03, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x36, 0x00, + 0x05, 0x00, // Capabilities + 0x01, 0x00, // Listen Interval + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x2E, 0x01, + 0x08, + 0x94, 11, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x00, // AID + 0x11, 0xD1, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0x49, 0x2D, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x53, 0x00, + 0x07, 0x00, // Capabilities + 0x00, 0x00, // Status code + 0x02, 0x00, // Association ID + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, // DMG Capabilities + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEB, // STA address + 0x02, // AID + 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, // DOT11_DMG_STA_CAPABILITY_INFO + 0x00, 0x00, // DOT11_DMG_PCP_AP_CAPABILITY_INFO + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x2C, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, + 0x96, 0x00, // For WiFi Beacon + // WiFi Beacon + 0x38, 0xE3, 0x3B, 0x64, 0x11, 0x00, 0x00, 0x00, // TimeStamp (9.4.1.10) + 0x64, 0x00, // Beacon Interval (8.4.1.3) + 0x05, 0x00, // Capability + + 0x00, 0x09, // SSID + 'W', 'D', 'I', '_', 'a', 'd', '_', 'O', 'N', // WDI_ad_ON + 0x03, 0x01, // DSS Parameters + 0x02, + 0x7F, 0x04, + 0x00, 0x00, 0x00, 0x02, + 0x94, 0x11, + 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, 0x01, 0xD2, 0xB7, 0x06, 0x00, 0x00, 0x40, 0x10, 0x00, + 0x00, + 0x97, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0xBE, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x12, + 0x00, 0x00, 0x03, 0xA4, 0x28, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x40, 0x00, 0x62, 0x32, + 0x10, 0x00, + 0x2E, 0x01, + 0x28, + 0xDD, 0x27, + 0x04, 0xCE, 0x14, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, + 0x00, 0x07, 0x00, 0x02, 0x00, 0x01, 0x00, + 0xDD, 0x0F, + 0x50, 0x6F, 0x9A, 0x17, 0x01, 0x09, 0x00, 0x07, 0x04, 0xCE, 0x14, 0x07, 0xA3, 0x66, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x09, 0x00, 0x00, 0x00 +}; + + +//=============================================================================== +// +// 11ax +// +//=============================================================================== + +// +// Open on 2.4 GHz +// +WDI_MAC_ADDRESS s_Connect_Addr_12_11ax_24_Open = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEC}; + + +UCHAR s_TLV_BSS_Entry_12_11ax_24_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x78, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEC, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x4A, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x11, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '2', '.', '4', + 0x01, 0x04, + 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, + 0x01, // DSSS Parameter + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x46, 0x05, + 0x02, 0x00, 0x00, 0x00, 0x00, // RM Enabled Capabilities + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_Success_AssociationResult_12_11ax_24_Open [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x28, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEC, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x4E, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x11, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '2', '.', '4', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x45, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x43, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x11, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '2', '.', '4', + 0x01, 0x04, + 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, + 0x01, // DSSS Parameter + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + + +//=============================================================================== + +// +// Open on 5 GHz +// +WDI_MAC_ADDRESS s_Connect_Addr_13_11ax_5_Open = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xED}; + + +UCHAR s_TLV_BSS_Entry_13_11ax_5_Open [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x76, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xED, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x48, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x0F, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '5', + 0x01, 0x04, + 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, + 0x01, // DSSS Parameter + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x46, 0x05, + 0x02, 0x00, 0x00, 0x00, 0x00, // RM Enabled Capabilities + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x24, 0x00, 0x00, 0x00, // Channel 36 + 0x02, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_Success_AssociationResult_13_11ax_5_Open [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0F, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xED, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x4C, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0xF, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '5', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x24, 0x30, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x45, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xFF, 0x13, // Extension IE + 0x23, // HE Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, // MAC Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PHY Capabilities + 0x00, + 0x00, 0x00, 0x00, 0x00, // HE-MCS and NSS + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x2C, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0xF, // SSID + 'W', 'D', 'I', '_', 'O', 'P', 'E', 'N', '_', '1', '1', 'a', 'x', '.', '5', + 0x01, 0x04, + 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, + 0x01, // DSSS Parameter + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +//=============================================================================== +// + +// #define SAE_MIXED_MODE 1 + +WDI_MAC_ADDRESS s_Connect_Addr_14_WPA3_SAE_CCMP = { 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32 }; + +UCHAR s_TLV_BSS_Entry_14_WPA3_SAE_CCMP [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type +#ifdef SAE_MIXED_MODE + 0x91, 0x00, //Len +#else + 0x8D, 0x00, //Len +#endif // SAE_MIXED_MODE + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, +#ifdef SAE_MIXED_MODE + 0x5E, 0x00, +#else + 0x5A, 0x00, +#endif // SAE_MIXED_MODE + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0C, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'A', 'E', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved +#ifdef SAE_MIXED_MODE + 0x30, 0x18, +#else + 0x30, 0x14, +#endif // SAE_MIXED_MODE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher +#ifdef SAE_MIXED_MODE + 0x02, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite - WPA2PSK + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - WPA3SAE + 0x80, 0x00, // RSN Capability - no MFPR or MFPC +#else + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - WPA3SAE + 0xC0, 0x00, // RSN Capability = MFP-Capable +#endif // SAE_MIXED_MODE + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId + +}; + +UCHAR s_TLV_Success_AssociationResult_14_WPA3_SAE_CCMP[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, +#ifdef SAE_MIXED_MODE + 0x2A, 0x01, +#else + 0x26, 0x01, +#endif // SAE_MIXED_MODE + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x4A, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0C, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'A', 'E', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x14, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise cipher count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AMK Suite Count + 0x00, 0x0F, 0xAC, 0x08, // AMK Suite - WPA3SAE + 0xC0, 0x00, // RSN Capability = MFP-Capable + MFP-Required + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, // Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x18, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, +#ifdef SAE_MIXED_MODE + 0x5E, 0x00, +#else + 0x5A, 0x00, +#endif // SAE_MIXED_MODE + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0C, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'A', 'E', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved +#ifdef SAE_MIXED_MODE + 0x30, 0x18, +#else + 0x30, 0x14, +#endif // SAE_MIXED_MODE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Multicast Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher +#ifdef SAE_MIXED_MODE + 0x02, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite - WPA2PSK + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - WPA3SAE + 0x80, 0x00, // RSN Cap = MFP-Capable +#else + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - WPA3SAE + 0xC0, 0x00, // RSN Cap = MFP-Capable + MFP required +#endif // SAE_MIXED_MODE + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + + +// +// SAE-Specific definitions :: Start +// +DWORD g_dwSaeResendConfirmRequested = 0; + +UCHAR pucSAECommitResponse [] = + { + 0x03, 0x00, // [1] usAlgorithmNumber = DOT11_AUTH_SAE (not-IE, 2 octets) + 0x01, 0x00, // [2] usXid: Commit=1, Confirm=2 (not-IE, 2 octets) + 0x00, 0x00, // [3] usStatusCode = 0 or 76 (ANTI_CLOGGING_TOKEN_REQUIRED) (not-IE, 2 octets) + 0x13, 0x00, // [10] FiniteCyclicGroup (not-IE, 2 octets) +// 0x00, 0x00, 0x00, 0x00, // [11] AntiCloggingToken (not-IE, variable octets) + // [13] AP Scalar + 0x93, 0x48, 0x89, 0xab, 0x38, 0x6b, 0x72, 0xd5, 0xff, 0x0d, 0x3c, 0xaa, 0x09, 0x56, 0x50, 0x20, + 0x2b, 0xd0, 0x3e, 0x26, 0x96, 0xb5, 0x90, 0x5f, 0x7b, 0x49, 0x5f, 0x3b, 0x7d, 0xc3, 0x5b, 0x48, + + // [14] AP Element + 0x58, 0x54, 0x5e, 0x6c, 0xa0, 0xe8, 0x86, 0xef, 0xfb, 0x05, 0x2a, 0xfb, 0x63, 0x2c, 0xa2, 0x19, + 0x5b, 0xb0, 0xb0, 0xa8, 0x25, 0xe5, 0x9d, 0xba, 0x6b, 0xaa, 0x0e, 0x93, 0xaf, 0x04, 0x6e, 0xf4, + 0xc9, 0x45, 0x5f, 0xec, 0x43, 0xfe, 0x5e, 0xb0, 0x2a, 0x6b, 0x8a, 0xbc, 0x8f, 0xd7, 0x07, 0x87, + 0x87, 0x3d, 0xd1, 0xd5, 0xd7, 0xfd, 0xe3, 0x07, 0x3a, 0x4c, 0xf3, 0xc2, 0xc7, 0x6f, 0x59, 0x5c, + }; +UCHAR pucSAECommitResponseReflection [] = + { + 0x03, 0x00, // [1] usAlgorithmNumber = DOT11_AUTH_SAE (not-IE, 2 octets) + 0x01, 0x00, // [2] usXid: Commit=1, Confirm=2 (not-IE, 2 octets) + 0x00, 0x00, // [3] usStatusCode = 0 or 76 (ANTI_CLOGGING_TOKEN_REQUIRED) (not-IE, 2 octets) + 0x13, 0x00, // [10] FiniteCyclicGroup (not-IE, 2 octets) +// 0x00, 0x00, 0x00, 0x00, // [11] AntiCloggingToken (not-IE, variable octets) + // [13] AP Scalar + + 0x49, 0x5c, 0x2c, 0xb4, 0x20, 0xec, 0xc9, 0xe8, 0xe8, 0x03, 0x2d, 0x00, 0x8d, 0xab, 0x4d, 0x91, + 0x70, 0x16, 0x06, 0x28, 0x40, 0x83, 0xb9, 0x8d, 0x19, 0xc6, 0x43, 0xcb, 0x63, 0x29, 0x9f, 0x03, + + // [14] AP Element + 0x13, 0x2e, 0xfc, 0x90, 0xb9, 0xd7, 0xb5, 0xc1, 0x2a, 0x1d, 0xe9, 0x05, 0x9c, 0xb3, 0xba, 0xc8, + 0xa6, 0x93, 0xff, 0xbf, 0x23, 0x02, 0x42, 0x3e, 0x58, 0xc2, 0x0d, 0x00, 0x10, 0xe8, 0x44, 0x60, + 0x9d, 0xfc, 0x34, 0x5e, 0x98, 0x8e, 0xf2, 0x12, 0x67, 0x24, 0xd0, 0x80, 0xfb, 0x2f, 0x1e, 0x7a, + 0xe6, 0x54, 0x01, 0x00, 0x50, 0xd4, 0xfe, 0x66, 0x47, 0x62, 0xc0, 0x3c, 0x9f, 0x7a, 0x10, 0x27, + }; + +UCHAR pucSAEConfirmResponse [] = + { + 0x03, 0x00, // [1] usAlgorithmNumber = DOT11_AUTH_SAE (not-IE, 2 octets) + 0x02, 0x00, // [2] usXid: Commit=1, Confirm=2 (not-IE, 2 octets) + 0x00, 0x00, // [3] usStatusCode = 0 or 76 (DOT11_FRAME_STATUS_ANTI_CLOGGING_TOKEN_REQUIRED) (not-Element, 2 octets) + 0x00, 0x00, // [12] SendConfirm (not-IE, 2 octets) + // [15] Confirm + 0xc7, 0xd1, 0x04, 0x94, 0x29, 0xec, 0xdf, 0x25, 0xda, 0xaa, 0x79, 0x6f, 0xda, 0xe9, 0x91, 0x9f, + 0x4b, 0x83, 0xad, 0xa3, 0x08, 0xde, 0x62, 0xca, 0xcd, 0x59, 0xfc, 0xf5, 0xc5, 0x4d, 0xeb, 0xd9, + }; + +UCHAR pucM1SaeFrame[] = +{ + // DOT11_MGMT_HEADER - DOT11_DATA_SHORT_HEADER + 0x88, 0x02, // Frame Control: Version = 0x0, Type = DOT11_FRAME_TYPE_DATA, Subtype = DOT11_DATA_SUBTYPE_DATA + 0x30, 0x00, // Duration + 0x9c, 0xda, 0x3e, 0xf2, 0x7d, 0xd5, // Address1: Receiver/Destination/STA address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Address2: Transmittor/Bssid address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Address3: Source address + 0x00, 0x00, 0x07, 0x00, // Sequence Control + // IEEE_8022_LLC_SNAP + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, // NWF_802_LLC_SNAP + 0x88, 0x8e, // sh_etype = DOT11_ETH_TYPE_EAPOL + // NWF_EAPOL_HEADER + 0x02, // Version = NWF_EAPOL_PROTOCOL_VERSION_V1 = 1 OR NWF_EAPOL_PROTOCOL_VERSION_V2 = 2 + 0x03, // Type = EAPOL_Key = 2 + 0x00, 0x75, // Length + // NWF_EAPOL_RSNA_KEY_DESC + 0x02, // Type + 0x00, 0x8a, // Info + 0x00, 0x10, // Length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Replay Counter + 0x57, 0x63, 0xf3, 0xb6, 0x6e, 0xc8, 0x90, 0xe4, 0xae, 0xfc, 0x2c, 0x50, 0xb0, 0xa9, 0x04, 0x29, // Nonce + 0x97, 0xb9, 0x80, 0x26, 0x13, 0x1a, 0xe2, 0xf0, 0x24, 0x30, 0x4b, 0x87, 0x57, 0x15, 0xcf, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RSC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MIC + 0x00, 0x16, // Key length + 0xdd, 0x14, // KeyData -> DOT11_INFO_ELEMENT_ID_VENDOR_SPECIFIC + Len + 0x00, 0x0f, 0xac, 0x04, // OUI -> RSN_KEY_DATA_OUI + RSN_KEY_DATA_OUI_TYPE_PMKID -> {0x00,0x0F,0xAC} + {0x04) + 0x37, 0xfb, 0x9a, 0x24, 0xc1, 0x57, 0x8c, 0xce, 0xc3, 0x60, 0x6c, 0x6f, 0x39, 0xe0, 0xb7, 0x02, // PMKID +}; + + +UCHAR pucExpectedM2SaeFrame[] = +{ + // DOT11_MGMT_HEADER - DOT11_DATA_SHORT_HEADER + 0x88, 0x01, // Frame Control + 0x2c, 0x00, // Duration + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Receiver/Destination/STA address + 0x9c, 0xda, 0x3e, 0xf2, 0x7d, 0xd5, // Transmittor/Bssid address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Source address + 0x00, 0x00, 0x07, 0x00, + // IEEE_8022_LLC_SNAP + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, // NWF_802_LLC_SNAP + 0x88, 0x8e, // sh_etype + // NWF_EAPOL_HEADER + 0x01, // Version = bProtocolVersion = NWF_EAPOL_PROTOCOL_VERSION_V1 = 1 + 0x03, // Type = EAPOL_Key = 2 + 0x00, 0x75, // Length + // NWF_EAPOL_RSNA_KEY_DESC + 0x02, // Type = bKeyDesc = NWF_EAPOL_KEY_DESC_RSNA = 2 + 0x01, 0x0a, // Info = usKeyInfo, ResponseKeyInfo.Version = KEY_DESC_VERSION_AES, Type=RSN_KEY_TYPE_PAIRWISE, MIC=1, Secure=0 + 0x00, 0x00, // Length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Replay Counter + 0x80, 0xf8, 0x10, 0x83, 0x4f, 0x0f, 0x40, 0xa1, 0xe5, 0x5d, 0x51, 0x92, 0x83, 0x4f, 0x8e, 0x98, // Nonce + 0x09, 0xca, 0xd5, 0x14, 0xc6, 0x08, 0x4c, 0xa9, 0xed, 0xc3, 0xa8, 0xff, 0xce, 0xc9, 0x36, 0xb6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RSC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0xa1, 0x79, 0x5f, 0x05, 0xa4, 0x12, 0x84, 0xf2, 0xf9, 0x0c, 0x79, 0x88, 0xeb, 0x92, 0x71, 0x62, // MIC + 0x00, 0x16, // Key Length + 0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, // Key Data = RSN + 0x00, 0x0f, 0xac, 0x08, 0x80, 0x00 + +}; + +UCHAR pucM3SaeFrame[] = +{ + // DOT11_MGMT_HEADER - DOT11_DATA_SHORT_HEADER + 0x88, 0x02, // Frame Control + 0x30, 0x00, // Duration + 0x9c, 0xda, 0x3e, 0xf2, 0x7d, 0xd5, // Receiver/Destination/STA address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Transmittor/Bssid address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Source address + 0x00, 0x00, 0x07, 0x00, // Sequence Control + // IEEE_8022_LLC_SNAP + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, // NWF_802_LLC_SNAP + 0x88, 0x8e, // sh_etype + // NWF_EAPOL_HEADER + 0x02, // Version + 0x03, // Type + 0x00, 0x97, // Length + // NWF_EAPOL_RSNA_KEY_DESC + 0x02, // Type + 0x13, 0xca, // Info + 0x00, 0x10, // Length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Replay Counter + 0x57, 0x63, 0xf3, 0xb6, 0x6e, 0xc8, 0x90, 0xe4, 0xae, 0xfc, 0x2c, 0x50, 0xb0, 0xa9, 0x04, 0x29, // Nonce + 0x97, 0xb9, 0x80, 0x26, 0x13, 0x1a, 0xe2, 0xf0, 0x24, 0x30, 0x4b, 0x87, 0x57, 0x15, 0xcf, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RSC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0xa5, 0xea, 0xdc, 0xfd, 0x97, 0xc7, 0x72, 0x76, 0x24, 0xe2, 0x7e, 0x71, 0x45, 0x3a, 0x24, 0xca, // MIC + 0x00, 0x38, // Key Length + 0x6f, 0x39, 0x30, 0x2c, 0x46, 0xb4, 0x3c, 0xf8, 0x42, 0x07, 0x8e, 0xc9, 0x65, 0x05, 0x2c, 0xd0, // Encrypted Key data + 0xe1, 0x7b, 0xdd, 0x2e, 0xbd, 0x69, 0x09, 0x1e, 0x39, 0xcc, 0x1a, 0xb3, 0x6e, 0x55, 0xd1, 0xad, + 0x5c, 0x45, 0x52, 0x4b, 0x83, 0x5d, 0x39, 0xe3, 0x1c, 0xb6, 0xed, 0x35, 0x52, 0x76, 0xb1, 0xc6, + 0x5a, 0x2c, 0x96, 0x07, 0x77, 0x15, 0x15, 0x5c, +}; + + +UCHAR pucExpectedM4SaeFrame[] = +{ + // DOT11_MGMT_HEADER - DOT11_DATA_SHORT_HEADER + 0x88, 0x01, // Frame Control + 0x2c, 0x00, // Duration + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Receiver/Destination/STA address + 0x9c, 0xda, 0x3e, 0xf2, 0x7d, 0xd5, // Transmittor/Bssid address + 0x34, 0x13, 0xe8, 0xbc, 0x4d, 0x32, // Source address + 0x10, 0x00, 0x07, 0x00, // Sequence Control + // IEEE_8022_LLC_SNAP + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, // NWF_802_LLC_SNAP + 0x88, 0x8e, // sh_etype + // NWF_EAPOL_HEADER + 0x01, // Version + 0x03, // Type + 0x00, 0x5f, // Length + // NWF_EAPOL_RSNA_KEY_DESC + 0x02, // Type + 0x03, 0x0a, // Info + 0x00, 0x00, // Length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Replay Counter + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Nonce + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RSC + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x52, 0x97, 0x0f, 0x90, 0x69, 0x7d, 0xcd, 0xeb, 0x98, 0xbf, 0xb1, 0x2a, 0xb2, 0x3e, 0xcc, 0x49, // MIC + 0x00, 0x00, // Key Length +}; + +// +// SAE-Specific definitions :: End +// + +// +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_15_WPA2PSK_SHA256 = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEF}; + +UCHAR s_TLV_BSS_Entry_15_WPA2PSK_SHA256 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x91, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEF, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x5e, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'H', 'A', '2', '5', '6', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1a, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x06, // AKM Suite + 0xCC, 0x00, // RSN Capability + 0x00, 0x00, + 0x00, 0x0F, 0xAC, 0x06, // Group Cipher + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_15_WPA2PSK_SHA256[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x28, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xEF, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x48, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'E', 'C', 'U', 'R', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x01, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x14, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise cipher count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AMK Suite Count + 0x00, 0x0F, 0xAC, 0x06, // AMK Suite - WPA2PSK_SHA256 + 0xC0, 0x00, // RSN Capability = MFP-Capable + MFP-Required + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x5e, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0A, // SSID + 'W', 'D', 'I', '_', 'S', 'E', 'C', 'U', 'R', 'E', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1a, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite + 0xCC, 0x00, // RSN Capability + 0x00, 0x00, + 0x00, 0x0F, 0xAC, 0x06, // Group Cipher + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + + +// +//=============================================================================== +// + +#ifdef WPA3_ARUBA_SIM +WDI_MAC_ADDRESS s_Connect_Addr_16_WPA3_SUITEB = {0xa8, 0xbd, 0x27, 0xcd, 0xe0, 0xa5}; // For Aruba +#elif WPA3_INTEL_SIM +WDI_MAC_ADDRESS s_Connect_Addr_16_WPA3_SUITEB = {0x8c, 0xfd, 0xf0, 0x0f, 0x7f, 0x4a}; // For Intel +#else +WDI_MAC_ADDRESS s_Connect_Addr_16_WPA3_SUITEB = {0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xF0}; +#endif + +UCHAR s_TLV_BSS_Entry_16_WPA3_SUITEB [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x97, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length +#ifdef WPA3_ARUBA_SIM + 0xa8, 0xbd, 0x27, 0xcd, 0xe0, 0xa5, // For Aruba +#elif WPA3_INTEL_SIM + 0x8c, 0xfd, 0xf0, 0x0f, 0x7f, 0x4a, // For Intel +#else + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xF0, +#endif + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x64, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x10, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'U', 'I', 'T', 'E', '_', 'B', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0x30, 0x1A, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x09, // Group Cipher = GCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x0C, // AKM Suite - WPA3-SuiteB + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId + +}; + +UCHAR s_TLV_Success_AssociationResult_16_WPA3_SUITEB[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x3A, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, +#ifdef WPA3_ARUBA_SIM + 0xa8, 0xbd, 0x27, 0xcd, 0xe0, 0xa5, // For Aruba +#elif WPA3_INTEL_SIM + 0x8c, 0xfd, 0xf0, 0x0f, 0x7f, 0x4a, // For Intel +#else + 0x00, 0xA0, 0xB0, 0xC0, 0xD0, 0xF0, +#endif + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x08, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_AUTH_ALGO_WPA3_ENT_192 = 8 + 0x09, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x09, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x0C, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_CIPHER_ALGO_BIP_GMAC_256 = C + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x54, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x10, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'U', 'I', 'T', 'E', '_', 'B', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, 0x07, 0x12, //Power Capability + 0x24, 0x02, 0x01, 0x0B, //Supported Channels + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x1A, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x09, // Group Cipher = GCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x0C, // AKM Suite - WPA3-SuiteB + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x64, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x10, // SSID + 'W', 'D', 'I', '_', 'W', 'P', 'A', '3', '-', 'S', 'U', 'I', 'T', 'E', '_', 'B', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1A, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x09, // Group Cipher = GCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x0C, // AKM Suite - WPA3-SuiteB + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, + +}; + +//=============================================================================== +// +// 6 GHz +// +//=============================================================================== + +// +// RNR IE has the following format (only care about TBTT length = 8 or 12): +// 0xc9, 0x<IELength> +// 0x<TBTTInformationHeader> -> 2 bytes (contains number and size of each element) +// 0x<OperatingClass>, 0x<Channel> -> 2 bytes (applies to all element in this list) +// 0x<TBTTOffset> -> 1 byte +// 0x<Bssid> -> 6 bytes +// [0x<SHortSsid>] -> 4 bytes +// 0x<BssParameters> -> 1 byte +// + +// +// Mac addresses have the following nomenclature for 6GHz Ssids +// +// 1st 3 bytes are 0x00 0xA1, 0xB0 +// 4th byte is for SSID: +// 01 = 6E__1 +// 02 = 6E__2 +// 03 = SSID3 +// 04 = SSID4 +// 5th Byte is for band: +// 02 = 2.4 GHz +// 05 = 5 GHz +// 06 = 6 GHz +// 6th byte is instance +// 01 = 1st instance +// 02 - 2nd instance +// : +// + +//=============================================================================== +// SIX_G: 6E__1: +// (1 * 2.4 GHz) + (1 * 5 GHz) + (2 * 6 GHz) +// 2.4 GHz: +// S1_24_1: S1_5_1 (In+Out) + S1_6_1 (Out) + S1_6_2 (Out) +// 5 GHz: +// S1_5_1: S1_24_1 (In+Out) + S1_6_1 (Out) + S1_6_2 (Out) +// 6 GHz: +// S1_6_1: S1_24_1 (In) + S1_5_1 (In) +// S1_6_2: S1_24_1 (In) + S1_5_1 (In) +//=============================================================================== + +// +// 6E__1: 1 * 2.4 GHz Bss's +// 1 RNR IE with 3 entries: Band:Channel = [5:36 + 6:101 + 6:133] +// +WDI_MAC_ADDRESS s_Connect_Addr_17_6G_S1_2_4_Ghz = {0x00, 0xA1, 0xB0, 0x01, 0x02, 0x01}; +UCHAR s_TLV_BSS_Entry_17_6G_S1_2_4_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xE9, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x01, 0x02, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xB6, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x01, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x30, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x73, 0x24, // Operating Class = 115 (5 GHz), Channel = 36 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x05, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 5 GHz + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 Ghz + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel / Freq = 2412 MHz + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_17_6G_S1_2_4_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0B, 0x02, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x01, 0x02, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8B, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0xa5, 0x09, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates + 0x30, 0x48, 0x60, 0x6c, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x78, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + 0x53, 0x53, 0x49, 0x44, 0x31, + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x01, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbit/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xb6, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x01, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x30, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x73, 0x24, // Operating Class = 115 (5 GHz), Channel = 36 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x05, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 5 GHz + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 Ghz + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +// 6E__1: 1 * 5 GHz Bss's +// 1 RNR IE with 3 entries: Band:Channel = [2.4:1 + 6:101 + 6:133] +// +WDI_MAC_ADDRESS s_Connect_Addr_18_6G_S1_5_Ghz = {0x00, 0xA1, 0xB0, 0x01, 0x05, 0x01}; +UCHAR s_TLV_BSS_Entry_18_6G_S1_5_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xe9, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x01, 0x05, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xb6, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x24, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x30, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x01, // Operating Class = 81 (2.4 GHz), Channel = 1 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x02, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 2.4 GHz + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 Ghz + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x24, 0x00, 0x00, 0x00, // Channel / Freq = 36 / 5180 MHz + 0x02, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_18_6G_S1_5_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0B, 0x02, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x01, 0x05, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8B, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0xa5, 0x09, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates + 0x30, 0x48, 0x60, 0x6c, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x78, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + 0x53, 0x53, 0x49, 0x44, 0x31, + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x24, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbit/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xb6, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x24, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x30, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x01, // Operating Class = 81 (2.4 GHz), Channel = 1 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x02, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 2.4 GHz + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 Ghz + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, 0x18, 0x3a, 0x94, 0x4f, 0x40, // 6E__1 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +// 6E__1: 1/2 * 6 GHz Bss's +// +WDI_MAC_ADDRESS s_Connect_Addr_19_6G_S1a_6_Ghz = {0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01}; +UCHAR s_TLV_BSS_Entry_19_6G_S1a_6_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC6, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x65, 0x00, 0x00, 0x00, // Channel / Freq = 101 / 6445 MHz + 0x05, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_19_6G_S1a_6_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xfD, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x05, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8E, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xff, 0x1e, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0x01, 0x78, 0x20, 0x0a, 0xc0, 0x8b, 0x0e, 0x30, 0x02, 0x00, 0xfd, 0x09, 0x8c, 0x0e, 0xcf, 0xf2, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x61, 0x1c, 0xc7, 0x71, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0x7d, 0x02, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x8A, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x65, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x65, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +// 6E__1: 2/2 * 6 GHz Bss's +// +WDI_MAC_ADDRESS s_Connect_Addr_20_6G_S1b_6_Ghz = {0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02}; +UCHAR s_TLV_BSS_Entry_20_6G_S1b_6_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC6, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x85, 0x00, 0x00, 0x00, // Channel / Freq = 133 / 6605 MHz + 0x05, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_20_6G_S1b_6_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xFD, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x01, 0x06, 0x02, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x05, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8E, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xff, 0x1e, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0x01, 0x78, 0x20, 0x0a, 0xc0, 0x8b, 0x0e, 0x30, 0x02, 0x00, 0xfd, 0x09, 0x8c, 0x0e, 0xcf, 0xf2, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x61, 0x1c, 0xc7, 0x71, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0x7d, 0x02, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x8A, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x85, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '1', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +//=============================================================================== +// SIX_G: 6E__2: +// (1 * 2.4 GHz) + (1 * 5 GHz) + (1 * 6 GHz) +// 2.4 GHz: +// S2_24_1: S2_5_1 (In+Out) + [S2_6_2 (Out)] +// 5 GHz: +// S2_5_1: S2_24_1 (In+Out) + S2_6_1 (Out) + [S2_6_2 (Out)] +// 6 GHz: +// S2_6_1: S2_5_1 (In) +//=============================================================================== + +// +// 6E__2: 1 * 2.4 GHz Bss's +// 2 RNR IEs with 1 entry each: Band:Channel = [5:44] + [6:101] +// +WDI_MAC_ADDRESS s_Connect_Addr_21_6G_S2_2_4_Ghz = {0x00, 0xA1, 0xB0, 0x02, 0x24, 0x01}; +UCHAR s_TLV_BSS_Entry_21_6G_S2_2_4_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xD3, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x02, 0x02, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xA0, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x06, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x0c, // RNR IE + 0x04, 0x08, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x08 = TBTT Length + 0x73, 0x2e, // Operating Class = 115 (5 GHz), Channel = 44 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, 0x40, // 6E__2 on 5 GHz + 0xc9, 0x0c, // RNR IE + 0x00, 0x08, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x08 = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0x42, // 6E__2 on 6 Ghz (Sabe Ssid) + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x06, 0x00, 0x00, 0x00, // Channel / Freq = 2437 MHz + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_21_6G_S2_2_4_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xF5, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x02, 0x02, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8B, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0xa5, 0x09, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates + 0x30, 0x48, 0x60, 0x6c, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x78, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + 0x53, 0x53, 0x49, 0x44, 0x31, + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x06, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbit/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xa0, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x06, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x0c, // RNR IE + 0x04, 0x08, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x08 = TBTT Length + 0x73, 0x2e, // Operating Class = 115 (5 GHz), Channel = 44 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, 0x40, // 6E__2 on 5 GHz + 0xc9, 0x0c, // RNR IE + 0x00, 0x08, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x08 = TBTT Length + 0x83, 0x65, // Operating Class = 131, Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0x42, // 6E__2 on 6 Ghz (Sabe Ssid) + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +// 6E__2: 1 * 5 GHz Bss's +// 3 RNR IEs with 1 entry each: Band:Channel = [2.4:6] + [6:101] + [6:133] +// +WDI_MAC_ADDRESS s_Connect_Addr_22_6G_S2_5_Ghz = {0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01}; +UCHAR s_TLV_BSS_Entry_22_6G_S2_5_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xed, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xba, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x2c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x10, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x02, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 2.4 GHz + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, (6 GHz) Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x42, // 6E__2 on 6 Ghz + 0xc9, 0x10, // RNR IE + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, (6 GHz) Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0xa2, 0x6b, 0x9d, 0xd6, 0x00, // 6E__2 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x2c, 0x00, 0x00, 0x00, // Channel / Freq = 44 / 5220 MHz + 0x02, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_22_6G_S2_5_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x0F, 0x02, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8B, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0xa5, 0x09, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates + 0x30, 0x48, 0x60, 0x6c, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x78, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + 0x53, 0x53, 0x49, 0x44, 0x31, + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x2c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbit/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xba, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x2c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0x10, // RNR IE + 0x04, 0x0c, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x02, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 2.4 GHz + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00 => B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x65, // Operating Class = 131, (6 GHz) Channel = 101 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x42, // 6E__2 on 6 Ghz + 0xc9, 0x10, // RNR IE + 0x0c, 0x0c, // TBTT: 0x0c => B2:3=1(FilteredAP:Reserved),B4-B7=f(TBTT Information Count=3+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131, (6 GHz) Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0xa2, 0x6b, 0x9d, 0xd6, 0x00, // 6E__2 on 6 GHz + + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +// +// 6E__2: 1 * 6 GHz Bss's +// +WDI_MAC_ADDRESS s_Connect_Addr_23_6G_S2_6_Ghz = {0x00, 0xA1, 0xB0, 0x02, 0x06, 0x01}; +UCHAR s_TLV_BSS_Entry_23_6G_S2_6_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC6, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x79, 0x00, 0x00, 0x00, // Channel / Freq = 121 / 6545 MHz + 0x05, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_23_6G_S2_6_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xFD, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x05, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8E, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xff, 0x1e, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0x01, 0x78, 0x20, 0x0a, 0xc0, 0x8b, 0x0e, 0x30, 0x02, 0x00, 0xfd, 0x09, 0x8c, 0x0e, 0xcf, 0xf2, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x61, 0x1c, 0xc7, 0x71, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0x7d, 0x02, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x8A, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x79, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +//=============================================================================== +// SIX_G: SSID3: +// (1 * 2.4 GHz) +// 2.4 GHz: +// S3_24_1: *S2_5_1 (Out)* +//=============================================================================== + +// +// SSID3: 1 * 2.4 GHz Bss's +// 2 RNR IEs with 1 entry each Band:Channel = [5:44 + 6:133] +// +WDI_MAC_ADDRESS s_Connect_Addr_24_6G_S3_2_4_Ghz = {0x00, 0xA1, 0xB0, 0x03, 0x02, 0x01}; +UCHAR s_TLV_BSS_Entry_24_6G_S3_2_4_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xDB, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x03, 0x02, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xa8, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '3', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x0a, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x73, 0x2e, // Operating Class = 115 (5 GHz), Channel = 44 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 5 GHz + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131 (6 GHz), Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel / Freq = 2457 MHz + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_24_6G_S3_2_4_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xFD, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x03, 0x02, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8B, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '3', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0xa5, 0x09, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates + 0x30, 0x48, 0x60, 0x6c, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x78, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + 0x53, 0x53, 0x49, 0x44, 0x31, + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0x0a, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbit/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0xa8, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '3', + 0x01, 0x08, // Supported Rates + 0x82, 0x84, 0x0b, 0x16, 0x8c, 0x12, 0x98, 0xa4, + 0x03, 0x01, // DS Parameter Set + 0x0a, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0x6c, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0x2d, 0x1a, // HT Capabilities (802.11n D1.10) + 0x76, 0x08, 0x17, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x04, // Extended Supported Rates 24, 36, 48, 54 [Mbits/sec] + 0x30, 0x48, 0x60, 0x6c, + 0x3d, 0x16, // HT Information (802.11n D1.10) + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x73, 0x2e, // Operating Class = 115 (5 GHz), Channel = 44 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x05, 0x01, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 5 GHz + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x83, 0x85, // Operating Class = 131 (6 GHz), Channel = 133 + 0x00, 0x00, 0xA1, 0xB0, 0x02, 0x06, 0x02, 0xa2, 0x6b, 0x9d, 0xd6, 0x40, // 6E__2 on 6 GHz + + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + + +//=============================================================================== +// SIX_G: SSID4 (non-colocated AP): +// (1 * 6 GHz) +// 6 GHz: +// S4_6_1: +//=============================================================================== + +// +// SSID4: 1 * 6 GHz Bss's +// +WDI_MAC_ADDRESS s_Connect_Addr_25_6G_S4_6_Ghz = {0x00, 0xA1, 0xB0, 0x04, 0x06, 0x01}; +UCHAR s_TLV_BSS_Entry_25_6G_S4_6_Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xC6, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA1, 0xB0, 0x04, 0x06, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '4', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0xe5, 0x00, 0x00, 0x00, // Channel / Freq = 229 / 7085 MHz + 0x05, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_25_6G_S4_6_Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xFD, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0x04, 0x06, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x07, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x04, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x04, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x05, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x8E, 0x00, + + 0x01, 0x11, // Capabilities + 0xfa, 0x00, // Listen Interval + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '4', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x21, 0x02, // Power Capability Min: 0, Max: 15 + 0x00, 0x0f, + 0x24, 0x32, // Supported Channels + 0x24, 0x01, 0x28, 0x01, 0x2c, 0x01, 0x30, 0x01, 0x34, 0x01, 0x38, 0x01, 0x3c, 0x01, 0x40, 0x01, + 0x64, 0x01, 0x68, 0x01, 0x6c, 0x01, 0x70, 0x01, 0x74, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x80, 0x01, + 0x84, 0x01, 0x88, 0x01, 0x8c, 0x01, 0x90, 0x01, 0x95, 0x01, 0x99, 0x01, 0x9d, 0x01, 0xa1, 0x01, + 0xa5, 0x01, + 0x46, 0x05, // RM Enabled Capabilities + 0x72, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x0a, // Extended Capabilities + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, // Vendor Specific: Microsoft Corp.: WMM/WME: Information Element + 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xff, 0x1e, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0x01, 0x78, 0x20, 0x0a, 0xc0, 0x8b, 0x0e, 0x30, 0x02, 0x00, 0xfd, 0x09, 0x8c, 0x0e, 0xcf, 0xf2, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x61, 0x1c, 0xc7, 0x71, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0x7d, 0x02, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x8A, 0x00, + + 0x01, 0x11, // Capabilities + 0x00, 0x00, // Status Code: Successful + 0x00, 0xc0, // Association ID: 0x0000 + 0x00, 0x05, // SSID Parameter set + '6', 'E', '_', '_', '2', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x03, 0x01, // DS Parameter set: Current Channel: 10 + 0xe5, + 0x0b, 0x05, // QBSS Load Element 802.11e CCA Version + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x93, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Inteval + 0x01, 0x00, // Capabilities + 0x00, 0x05, // SSID + '6', 'E', '_', '_', '4', + 0x01, 0x08, // Supported Rates + 0x8c, 0x12, 0x98, 0xa4, 0x30, 0x48, 0x60, 0x6c, + 0x05, 0x04, // TIM - DTIM 0 of 0 + 0x00, 0x02, 0x00, 0xa4, + 0x0b, 0x05, + 0x00, 0x00, 0x00, 0x12, 0x7a, + 0x2a, 0x01, // ERP Information + 0x00, + 0xdd, 0x18, // Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, + 0x42, 0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, + 0xff, 0x03, // Ext Tag: HE Extended Capabilities (802.11ax/D3.0) + 0x3b, + 0xbd, 0x02, + 0xff, 0x27, // Ext Tag: HE Capabilities (802.11ax/D3.0) + 0x23, + 0xf7, 0x70, 0x99, 0x16, 0x64, 0x00, 0x0e, 0x30, 0x0c, 0xb6, 0x02, 0x1b, 0xb4, 0x0c, 0xcf, 0x30, + 0x00, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0xfa, 0xff, 0x7b, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, + 0xff, 0x0c, // Ext Tag: HE Operation (802.11ax/D3.0) + 0x24, + 0xf4, 0x3f, 0x02, 0x00, 0xf0, 0xff, 0x05, 0x03, 0x07, 0x0f, 0x00, + 0xff, 0x0e, // Ext Tag: MU EDCA Parameter Set + 0x26, + 0xc0, 0x07, 0xa4, 0x01, 0x23, 0xa4, 0x01, 0x42, 0x43, 0x01, 0x62, 0x32, 0x01, + + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0A, 0x00, 0x00, 0x00, + +}; + +//=============================================================================== +// WDI_OWE_RNR +//=============================================================================== + + +/// WDI_OWE_RNR +/// +/// Description +/// - Non-Transition mode OWE network +/// - Advertises Reduced Neighbor Reports (RNRs) for the OWE Transition Mode BSSes WDI_OWE_TM_OWE and WDI_OWE_TM_OPEN +/// - Note: The OWE TM BSSes do not advertise RNR IEs +/// - Definitions for these two Transition Mode networks follows this one +/// +/// Intention +/// - Test Non-Transition Mode OWE networks +/// - Test discovery of OWE Transition Mode network via RNR prior to receiving beacon or probe +/// - Since the networks are indicated in order during scans (i.e. the OWE TM networks will be indicated after this one) +/// it is expected that RNR for the OWE TM networks will be received before their beacons and probes. +/// +/// Expectation +/// - Scan results display WDI_OWE_RNR as an Enhanced Open network to which connections are supported +/// - The RNR will not effect connections to or display of OWE Transition Mode networks that it contains +/// +/// Limitations +/// - Connections to this network will fail because the driver does not OWE DH Handshake +WDI_MAC_ADDRESS s_ConnectAddr_26_OWE_With_RNR = {00, 0xA0, 0xB0, 0xC0, 0xD1, 0xFF}; +UCHAR s_TLV_BSS_Entry_26_OWE_With_RNR [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xB6, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0xFF, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x83, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0B, // SSID + 'W', 'D', 'I', '_', 'O', 'W', 'E', '_', 'R', 'N', 'R', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1a, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x12, // AKM Suite - OWE + 0xC0, 0x00, // RSN Capability - MFP Req + Capable + 0x00, 0x00, + 0x00, 0x0F, 0xAC, 0x06, // Group Cipher + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x0B, // Operating Class = 81 (2.4 GHz), Channel = B + 0x00, // TBTT Offset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x00, // MAC Address --> OWE Transition Mode OWE (Defined below) + 0xFD, 0x1F, 0x3F, 0x49, // Short SSID for WDI_OWE_TM_OWE + 0x00, // BssParameters + + 0xc9, 0x10, // RNR IE + 0x00, 0x0c, // TBTT: 0x00,B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x0B, // Operating Class = 81 (2.4 GHz), Channel = B + 0x00, // TBTT Offset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x01, // MAC Address --> OWE Transition Mode Open (Defined below) + 0x21, 0x24, 0x6C, 0x85, // Short SSID for WDI_OWE_TM_OPEN + 0x00, // BssParameters + + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +// Test client hasn't implemented OWE DH handshake, so just indicate assoc failure +UCHAR s_TLV_Failure_AssociationResult_26_OWE_With_RNR [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x46, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0xC0, 0xD1, 0xFF, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x01, 0x00, 0x00, 0x00, // Association Status: WDI_ASSOC_STATUS_FAILURE + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, // AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x00, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +/// WDI_OWE_TM_OWE +/// Description +/// - OWE BSS of OWE Transition Mode network +/// - Auth Type is OWE +/// - Partner BSS is the OWE Transition Mode Open BSS "WDI_OWE_TM_OPEN" +/// - Per the spec, this network is hidden and contains an OWE TM element listing information about the partner BSS +/// - Listed in RNR of BSS WDI_OWE_RNR +/// - RNR IEs are not avertised by this BSS +/// +/// Intention +/// - Test OWE Transition Mode +/// - Test discovery of OWE Transition Mode network via RNR prior to receiving a beacon or probe +/// - Since the networks are indicated in order during scans, the RNR for this network will be received before its beacon. +/// +/// Expectation +/// - The OWE spec requires the STA to display the SSID of the Open BSS to the user for interoperability. User initiated connections to the SSID of the Open BSS +/// will initiate a connection to the OWE BSS and this is reflected in the security type in the UI. This allows STAs to view the same network SSID regardless of their +/// support for OWE, while also allowing the most secure connection to be made. +/// +/// - The UI will display: +/// - SSID: "WDI_OWE_TM_OPEN" (The SSID of the Open BSS) +/// - A hidden BSS may also be displayed, but only a single entry with an SSID is expected +/// - Security Description: "Enhanced Open" +/// - "Secured" or a lock icon should not be displayed +/// - No password prompt on connect +/// - "Connect" will initiate a connection to the OWE Transition Mode BSS Entry +/// - In the entry containing the BSSID of the OWE TM OWE BSS, "netsh wlan show networks mode=bss" displays +/// - SSID: "WDI_OWE_TM_OPEN" +/// - Authentication: OWE +/// - Encryption: CCMP +/// - MFP Required: 1 +/// +/// Limitations +/// - Connections to this network will fail because the driver does not OWE DH Handshake +WDI_MAC_ADDRESS s_ConnectAddr_27_OWE_TM_OWE = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x00}; +UCHAR s_TLV_BSS_Entry_27_OWE_TM_OWE [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xA1, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x00, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x6e, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1a, // RSN IE + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher + 0x01, 0x00, // AKM Suite count + 0x00, 0x0F, 0xAC, 0x12, // AKM Suite - OWE + 0xC0, 0x00, // RSN Capability - MFP Req + Capable + 0x00, 0x00, + 0x00, 0x0F, 0xAC, 0x06, // Group Cipher + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + 0xDD, 0x1A, // Vendor specific - OWE Transition Mode + 0x50, 0x6F, 0x9A, 0x1C, // WFA OUI + OWE TM OUI (0x1C) + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x01, // Partner BSS BSSID + 0x0F, // Partner BSS SSID Length + 'W', 'D', 'I', '_', 'O', 'W', 'E', '_', 'T', 'M', '_', 'O', 'P', 'E', 'N', // Partner BSS SSID + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +// Test client hasn't implemented simulated OWE DH handshake, so just indicate assoc failure +UCHAR s_TLV_Failure_AssociationResult_27_OWE_TM_OWE [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x46, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA1, 0xB0, 0xC0, 0xD1, 0x00, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x01, 0x00, 0x00, 0x00, //Association Status: WDI_ASSOC_STATUS_FAILURE + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x00, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +/// WDI_OWE_TM_OPEN +/// Description +/// - Open BSS of OWE Transition Mode network +/// - Open network +/// - Partner BSS is the OWE Transition Mode OWE BSS "WDI_OWE_TM_OWE" +/// - Per the spec, this network is hidden and contains an OWE TM element listing information about the partner BSS +/// - Listed in RNR of BSS WDI_OWE_RNR +/// - RNR IEs are not avertised by this BSS +/// +/// Intention +/// - Test OWE Transition Mode +/// - Test discovery of OWE Transition Mode network via RNR prior to receiving a beacon or probe +/// - Since the networks are indicated in order during scans, the RNR for this network will be received before its beacon. +/// +/// Expectation +/// - The OWE spec requires the STA to display the SSID of the Open BSS to the user for interoperability. User initiated connections to the SSID of the Open BSS +/// will initiate a connection to the OWE BSS and this is reflected in the security type in the UI. This allows STAs to view the same network SSID regardless of their +/// support for OWE, while also allowing the most secure connection to be made. +/// +/// - The UI will display: +/// - SSID: "WDI_OWE_TM_OPEN" (The SSID of the Open BSS) +/// - A hidden BSS may also be displayed, but only a single entry with an SSID is expected +/// - Security Description: "Enhanced Open" +/// - "Secured" or a lock icon should not be displayed +/// - No password prompt on connect +/// - "Connect" will initiate a connection to the OWE Transition Mode BSS Entry +/// - In the entry containing the BSSID of this BSS, "netsh wlan show networks mode=bss" displays +/// - SSID: (Hidden) +/// - Authentication: Open +/// - Encryption: None +/// +/// Limitations +/// - Connections to this network will fail because the driver does not OWE DH Handshake +WDI_MAC_ADDRESS s_ConnectAddr_28_OWE_TM_Open = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x01}; +UCHAR s_TLV_BSS_Entry_28_OWE_TM_Open_Beacon [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x95, 0x00, // Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x01, + + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x62, 0x00, // Length + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x0F, // SSID + 'W', 'D', 'I', '_', 'O', 'W', 'E', '_', 'T', 'M', '_', 'O', 'P', 'E', 'N', + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x32, 0x04, 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + 0xDD, 0x19, // Vendor specific - OWE Transition Mode + 0x50, 0x6F, 0x9A, 0x1C, // WFA OUI + OWE TM OUI (0x1C) + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x00, // Partner BSS BSSID + 0x0E, // Partner BSS SSID Length + 'W', 'D', 'I', '_', 'O', 'W', 'E', '_', 'T', 'M', '_', 'O', 'W', 'E', // Partner BSS SSID + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x0B, 0x00, 0x00, 0x00, // Channel + 0x01, 0x00, 0x00, 0x00 // BandId +}; + +// Test client hasn't implemented OWE DH handshake, so just indicate assoc failure +UCHAR s_TLV_Failure_AssociationResult_28_OWE_TM_Open [] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0x46, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x01, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x01, 0x00, 0x00, 0x00, //Association Status: WDI_ASSOC_STATUS_FAILURE + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x00, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, // DisableDataPathOffloadsScenario + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +//=============================================================================== +// +// Wi-Fi 7 +// +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_29_WiFi7_Mixed_MLD = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x02}; +WDI_MAC_ADDRESS s_Connect_Addr_30_WiFi7_Mixed_Link_1 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x03}; +WDI_MAC_ADDRESS s_Connect_Addr_31_WiFi7_Mixed_Link_2 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x04}; +WDI_MAC_ADDRESS s_Connect_Addr_32_WiFi7_Mixed_Link_3 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x05}; + +UCHAR s_TLV_BSS_Entry_30_WiFi7_Mixed_Link_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xfa, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x03, // Link 1 MAC address + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0xc7, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0f, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'M', 'i', 'x', 'e', 'd', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0x32, 0x01, // DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES + 0xFB, // BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY + 0x30, 0x2a, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher = CCMP + 0x03, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher = CCMP-128 + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher = GCMP-128 + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP-256 + 0x03, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite - PSK + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - SAE-256 + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xCC, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // [B7-B4] [B3-B0] [B15-B12] [b11-B8] + // [EML=0 + Medium=0 + BSS=1 + LinkID=1] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=0] + 0x20, 0x00, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x02, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x04, // STA Info : AP Link 1 MAC address + // Remaining STA Profile for Link 2 + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x05, // STA Info : AP Link 2 MAC address + // Remaining STA Profile for Link 3 + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x04, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x05, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x24, 0x00, 0x00, 0x00, // Channel + 0x02, 0x00, 0x00, 0x00 // BandId + +}; + +UCHAR s_TLV_Success_AssociationResult_30_WiFi7_Mixed_Link_1[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xc0, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x03, // AP Link 1 Mac Address + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x08, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_AUTH_ALGO_WPA3_SAE = 9 + 0x09, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x09, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x0C, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_CIPHER_ALGO_BIP_GMAC_256 = C + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x7e, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0f, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'M', 'i', 'x', 'e', 'd', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x1A, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher = CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP-256 + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // Sta MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x21, // STA Info : STA Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x22, // STA Info : Sta Link 2 MAC address + // STA Profile + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x55, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, + 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x02, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x04, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x05, // STA Info : AP Link 2 MAC address + // STA Profile + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x9b, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0f, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'M', 'i', 'x', 'e', 'd', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x32, 0x01, + 0xFB, // H2E Only + 0x30, 0x2a, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x09, // Group Cipher = GCMP + 0x03, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x04, // Pairwise Cipher = CCMP-128 + 0x00, 0x0F, 0xAC, 0x08, // Pairwise Cipher = GCMP-128 + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP-256 + 0x03, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x02, // AKM Suite - PSK + 0x00, 0x0F, 0xAC, 0x08, // AKM Suite - SAE-256 + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x02, // MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x04, // STA Info : MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x05, // STA Info : MAC address + // STA Profile + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, // dot11_phy_type_eht + +}; + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_33_WiFi7_Open_MLD = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06}; +WDI_MAC_ADDRESS s_Connect_Addr_34_WiFi7_Open_Link_1 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x07}; +WDI_MAC_ADDRESS s_Connect_Addr_35_WiFi7_Open_Link_2 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08}; +WDI_MAC_ADDRESS s_Connect_Addr_36_WiFi7_Open_Link_3 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09}; + +UCHAR s_TLV_BSS_Entry_34_WiFi7_Open_Link_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xca, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x07, // AP Link 1 address + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x97, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x01, 0x00, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'O', 'p', 'e', 'n', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // [B7-B4] [B3-B0] [B15-B12] [b11-B8] + // [EML=0 + Medium=0 + BSS=1 + LinkID=1] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=0] + 0x20, 0x00, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link2 MAC address + // Remaining STA Profile for Link 2 + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x37, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 3 MAC address + // Remaining STA Profile for Link 3 + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x9d, 0x00, 0x00, 0x00, // Channel + 0x02, 0x00, 0x00, 0x00 // BandId + +}; + +UCHAR s_TLV_Success_AssociationResult_34_WiFi7_Open_Link_1[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xb3, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x07, // AP Link 1 Mac Address + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_CIPHER_ALGO_NONE = 0 + 0x00, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x75, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'O', 'p', 'e', 'n', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0xff, 0x3d, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // Multi-Link Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x80, 0x01, // [EML=1 + Medium=0 + BSS=0 + LinkID=0] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=1] + 0x0b, // Common Info length + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // Local STA MLD Mac address (required for Basic) + // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + 0x81, 0x00, 0x00, // [ EML Capabilities (3 octets) ] + 0x02, 0x00, // [ MLD Capabilities (2 octets) - (2 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x32, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0010] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x21, // STA Info : Local Link 1 MAC address + // STA Profile + // Remaining STA Profile for Link 2 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length = 21 + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x22, // STA Info : Local Sta Link 2 MAC address + // STA Profile + // Remaining STA Profile for Link 3 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x55, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x07, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link 2 MAC address + // STA Profile + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x97, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x01, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'O', 'p', 'e', 'n', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 2 MAC address + // STA Profile + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, // dot11_phy_type_eht + +}; + +//=============================================================================== + +WDI_MAC_ADDRESS s_Connect_Addr_37_WiFi7_Only_MLD = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0a}; +WDI_MAC_ADDRESS s_Connect_Addr_38_WiFi7_Only_Link_1 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0b}; +WDI_MAC_ADDRESS s_Connect_Addr_39_WiFi7_Only_Link_2 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0c}; +WDI_MAC_ADDRESS s_Connect_Addr_40_WiFi7_Only_Link_3 = {0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0d}; + +UCHAR s_TLV_BSS_Entry_38_WiFi7_Only_Link_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xe8, 0x00, //Len + + // WDI_TLV_BSSID = 10 = 0xa + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0b, // Link 1 MAC address + + // WDI_TLV_BEACON_FRAME = 143 = 0x8f + 0x0a, 0x00, + 0xb5, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x10, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'a', 'k', 'm', ':', '2', '4', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0x30, 0x1a, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher = CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP-256 + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xCC, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // [B7-B4] [B3-B0] [B15-B12] [b11-B8] + // [EML=0 + Medium=0 + BSS=1 + LinkID=1] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=0] + 0x20, 0x00, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0a, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0c, // STA Info : AP Link 1 MAC address + // Remaining STA Profile for Link 2 + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0d, // STA Info : AP Link 2 MAC address + // Remaining STA Profile for Link 3 + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0c, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x32, 0x01, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0d, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x32, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + + 0x32, 0x04, // Extended Supported Rates: DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES + 0x0C, 0x12, 0x18, 0xFB, // 0xFB = BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, // Channel + 0x05, 0x00, 0x00, 0x00 // BandId +}; + +UCHAR s_TLV_Success_AssociationResult_38_WiFi7_Only_Link_1[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xaf, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0b, // AP Link 1 Mac Address + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x08, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_AUTH_ALGO_WPA3_SAE = 9 + 0x09, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x09, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_CIPHER_ALGO_GCMP_256 = 9 + 0x0C, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_CIPHER_ALGO_BIP_GMAC_256 = C + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x01, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x7f, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x10, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'a', 'k', 'm', ':', '2', '4', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0x30, 0x1A, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x04, // Group Cipher = CCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // Sta MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x21, // STA Info : STA Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x22, // STA Info : Sta Link 2 MAC address + // STA Profile + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x55, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, + 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0a, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0c, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0d, // STA Info : AP Link 2 MAC address + // STA Profile + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x89, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x10, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'a', 'k', 'm', ':', '2', '4', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, 0x06, // DSS Parameters + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, 0x00, // ERP + 0x2F, 0x01, 0x00, // Reserved + 0x30, 0x1a, + 0x01, 0x00, // Version + 0x00, 0x0F, 0xAC, 0x09, // Group Cipher = GCMP + 0x01, 0x00, // Pairwise Cipher Count + 0x00, 0x0F, 0xAC, 0x09, // Pairwise Cipher = GCMP + 0x01, 0x00, // AKM Suite Count + 0x00, 0x0F, 0xAC, 0x18, // AKM Suite - SAE-384 (Wi-Fi 7) + 0xC0, 0x00, // RSN Capability = MFPC + MFPR + ... + 0x00, 0x00, // PMKID Count + 0x00, 0x0F, 0xAC, 0x0C, // Group Mgmt Cipher = GMAC + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0a, // MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0c, // STA Info : MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x0d, // STA Info : MAC address + // STA Profile + 0x32, 0x04, // Extended Supported Rates: DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES + 0x0C, 0x12, 0x18, 0xFB, // 0xFB = BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, // dot11_phy_type_eht + +}; + +//=============================================================================== +// DualSta networks +//=============================================================================== +// + +WDI_MAC_ADDRESS s_Connect_Addr_41_DualSta_5Ghz = {0x00, 0x51, 0x30, 0x40, 0x50, 0x60}; +UCHAR s_TLV_BSS_Entry_41_DualSta_5Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x63, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0x51, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x35, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x04, // Supported Rates + 0x02, 0x04, 0x0B, 0x16, + 0x03, 0x01, // DSSS Parameter + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x46, 0x05, // RM Enabled Capabilities + 0x02, 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x07, // Vendor specific - MBO-OCE IE + 0x50, 0x6F, 0x9A, // WFA OUI + 0x16, // MBO-OCE IE OUI Type + 0x01, // Attribute ID - AP capability + 0x01, // Attrib length + 0x00, // Not cellular data aware + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x24, 0x00, 0x00, 0x00, // Channel + 0x02, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_SuccessOpenAssociationResult_41_DualSta_5Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD7, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0x51, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x30, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x08, // Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x21, 0x02, // Power Capability + 0x07, 0x12, + 0x24, 0x02, // Supported Channels + 0x01, 0x0B, + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x07, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, //Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x32, 0x04, //Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x18, //WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, + +}; + +// ----- + +WDI_MAC_ADDRESS s_Connect_Addr_42_DualSta_6Ghz = {0x00, 0x52, 0x30, 0x40, 0x50, 0x60}; +UCHAR s_TLV_BSS_Entry_42_DualSta_6Ghz [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0x63, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x00, 0x52, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_PROBE_RESPONSE_FRAME + 0x09, 0x00, // Type + 0x35, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x04, // Supported Rates + 0x02, 0x04, 0x0B, 0x16, + 0x03, 0x01, // DSSS Parameter + 0x01, + 0x05, 0x04, // TIM + 0x00, 0x01, 0x00, 0x00, + 0x46, 0x05, // RM Enabled Capabilities + 0x02, 0x00, 0x00, 0x00, 0x00, + 0xDD, 0x07, // Vendor specific - MBO-OCE IE + 0x50, 0x6F, 0x9A, // WFA OUI + 0x16, // MBO-OCE IE OUI Type + 0x01, // Attribute ID - AP capability + 0x01, // Attrib length + 0x00, // Not cellular data aware + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x04, 0x00, + 0x04, 0x05, 0x06, 0x07, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_CHANNEL_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x09, 0x00, 0x00, 0x00, // Channel + 0x05, 0x00, 0x00, 0x00 // Band ID +}; + +UCHAR s_TLV_SuccessOpenAssociationResult_42_DualSta_6Ghz[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xD7, 0x00, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x00, 0x52, 0x30, 0x40, 0x50, 0x60, + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, //Association Status + 0x00, 0x00, 0x00, 0x00, //Status Code + 0x00, //ReAssociationRequest + 0x01, 0x00, 0x00, 0x00, //AuthAlgorithm + 0x00, 0x00, 0x00, 0x00, //UnicastCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastDataCipherAlgorithm + 0x00, 0x00, 0x00, 0x00, //MulticastMgmtCipherAlgorithm + 0x00, //FourAddressSupported + 0x00, //Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, //DSInfo + 0x00, 0x00, 0x00, 0x00, //AssociationComebackTime + 0x05, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x30, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x08, // Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x21, 0x02, // Power Capability + 0x07, 0x12, + 0x24, 0x02, // Supported Channels + 0x01, 0x0B, + 0x32, 0x04, // Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x07, // WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x30, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, //Rates + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, + 0x32, 0x04, //Extended Rates + 0x0C, 0x12, 0x18, 0x60, + 0xDD, 0x18, //WMM settings + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, + 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, + + // WDI_TLV_BEACON_PROBE_RESPONSE + 0x30, 0x00, // Type + 0x25, 0x00, // Length + 0x00, 0x11, 0x22, 0x33, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x00, 0x04, // Capability + 0x00, 0x08, + 'D', 'u', 'a', 'l', '-', 'S', 't', 'a', // SSID + 0x01, 0x04, 0x02, 0x04, 0x0B, 0x16, // Supported Rates + 0x03, 0x01, 0x01, // DSSS Parameter + 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, // TIM + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x07, 0x00, 0x00, 0x00, + +}; + +//=============================================================================== +// Data throughput test networks +//=============================================================================== +// + +__declspec(selectany) WDI_MAC_ADDRESS s_Connect_Addr_43_Speed_01_WiFi7_Open_Link_1 = {0x22, 0x22, 0x22, 0x22, 0x00, 0x01}; +__declspec(selectany) WDI_MAC_ADDRESS s_Connect_Addr_44_Speed_02_WiFi7_Open_Link_1 = {0x22, 0x22, 0x22, 0x22, 0x00, 0x02}; +__declspec(selectany) UCHAR s_TLV_BSS_Entry_43_WiFi7_Open_Link_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xca, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x22, 0x22, 0x22, 0X22, 0x00, 0x01, // AP Link 1 address + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x97, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x01, 0x00, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '1', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // [B7-B4] [B3-B0] [B15-B12] [b11-B8] + // [EML=0 + Medium=0 + BSS=1 + LinkID=1] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=0] + 0x20, 0x00, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link2 MAC address + // Remaining STA Profile for Link 2 + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x37, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 3 MAC address + // Remaining STA Profile for Link 3 + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x9d, 0x00, 0x00, 0x00, // Channel + 0x02, 0x00, 0x00, 0x00 // BandId + +}; + +__declspec(selectany) UCHAR s_TLV_Success_AssociationResult_43_WiFi7_Open_Link_1[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xb3, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x22, 0x22, 0x22, 0x22, 0x00, 0x01, // AP Link 1 Mac Address + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_CIPHER_ALGO_NONE = 0 + 0x00, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x75, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '1', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0xff, 0x3d, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // Multi-Link Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x80, 0x01, // [EML=1 + Medium=0 + BSS=0 + LinkID=0] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=1] + 0x0b, // Common Info length + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // Local STA MLD Mac address (required for Basic) + // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + 0x81, 0x00, 0x00, // [ EML Capabilities (3 octets) ] + 0x02, 0x00, // [ MLD Capabilities (2 octets) - (2 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x32, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0010] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x21, // STA Info : Local Link 1 MAC address + // STA Profile + // Remaining STA Profile for Link 2 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length = 21 + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x22, // STA Info : Local Sta Link 2 MAC address + // STA Profile + // Remaining STA Profile for Link 3 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x55, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x22, 0x22, 0x22, 0x22, 0x00, 0x01, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x22, 0x22, 0x22, 0x22, 0x00, 0x02, // STA Info : AP Link 2 MAC address + // STA Profile + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x97, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x01, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '1', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 2 MAC address + // STA Profile + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, // dot11_phy_type_eht + +}; + + +__declspec(selectany) UCHAR s_TLV_BSS_Entry_44_WiFi7_Open_Link_1 [] = +{ + // WDI_TLV_BSS_ENTRY + 0x08, 0x00, //Type + 0xca, 0x00, //Len + + // WDI_TLV_BSSID + 0x02, 0x00, // Type + 0x06, 0x00, // Length + 0x22, 0x22, 0x22, 0x22, 0x00, 0x02, // AP Link 1 address + // WDI_TLV_BEACON_FRAME + 0x0a, 0x00, + 0x97, 0x00, + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x64, 0x00, // Beacon Interval + 0x01, 0x00, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '2', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // [B7-B4] [B3-B0] [B15-B12] [b11-B8] + // [EML=0 + Medium=0 + BSS=1 + LinkID=1] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=0] + 0x20, 0x00, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link2 MAC address + // Remaining STA Profile for Link 2 + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x37, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 3 MAC address + // Remaining STA Profile for Link 3 + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_BSS_ENTRY_DEVICE_CONTEXT + 0x0d, 0x00, + 0x09, 0x00, + 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, + + // WDI_TLV_BSS_ENTRY_SIGNAL_INFO + 0x0b, 0x00, + 0x08, 0x00, + 0xCE, 0xFF, 0xFF, 0xFF, // RSSI + 0x5A, 0x00, 0x00, 0x00, // Link Quality + + // WDI_TLV_BSS_ENTRY_PHY_INFO + 0x3a, 0x00, + 0x08, 0x00, + 0x9d, 0x00, 0x00, 0x00, // Channel + 0x02, 0x00, 0x00, 0x00 // BandId + +}; + +__declspec(selectany) UCHAR s_TLV_Success_AssociationResult_44_WiFi7_Open_Link_1[] = +{ + // WDI_TLV_ASSOCIATION_RESULT + 0x35, 0x00, + 0xb3, 0x01, + + // WDI_TLV_BSSID + 0x02, 0x00, + 0x06, 0x00, + 0x22, 0x22, 0x22, 0x22, 0x00, 0x02, // AP Link 1 Mac Address + + // WDI_TLV_ASSOCIATION_RESULT_PARAMETERS + 0x2D, 0x00, + 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, // Association Status + 0x00, 0x00, 0x00, 0x00, // Status Code + 0x00, // ReAssociationRequest + 0x00, 0x00, 0x00, 0x00, // AuthAlgorithm = WDI_CIPHER_ALGO_NONE = 0 + 0x00, 0x00, 0x00, 0x00, // UnicastCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastDataCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, 0x00, 0x00, 0x00, // MulticastMgmtCipherAlgorithm = WDI_AUTH_ALGO_80211_OPEN = 0 + 0x00, // FourAddressSupported + 0x00, // Port Authorized + 0x00, // WMM QoS Enabled + 0x00, 0x00, 0x00, 0x00, // DSInfo + 0x00, 0x00, 0x00, 0x00, // AssociationComebackTime + 0x02, 0x00, 0x00, 0x00, // Band ID + 0x00, 0x00, 0x00, 0x00, // IHV Association Status + 0x00, 0x00, 0x00, 0x00, //DisableDataPathOffloadsScenario + + // WDI_TLV_ASSOCIATION_REQUEST_FRAME + 0x2E, 0x00, + 0x75, 0x00, + 0x21, 0x04, // Capabilities + 0x0A, 0x00, // Listen Interval + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '2', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Rates + 0x21, 0x02, + 0x07, 0x12, //Power Capability + 0x24, 0x02, + 0x01, 0x0B, //Supported Channels + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x08, + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x03, // WMM settings + 0xff, 0x3d, // Multilink Extension Element + 0x6B, // Multilink Extension ID + // Multi-Link Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x80, 0x01, // [EML=1 + Medium=0 + BSS=0 + LinkID=0] [Reserved=0 + Basic=0] [Reserved=0000] [Reserved=000 MLD=1] + 0x0b, // Common Info length + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, // Local STA MLD Mac address (required for Basic) + // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + 0x81, 0x00, 0x00, // [ EML Capabilities (3 octets) ] + 0x02, 0x00, // [ MLD Capabilities (2 octets) - (2 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x32, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0010] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x21, // STA Info : Local Link 1 MAC address + // STA Profile + // Remaining STA Profile for Link 2 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x15, // Length = 21 + // STA Control = [B7-B4] [B3-B0] [B15-B12] [b11-B8] + 0x33, 0x00, // [DTIM=0 + BeaconInt=0 + MAC=1 + Complete=1] [LinkID=0011] [Reserved=0000] [Reserved=0 + BSS=0 + NTSRBit=0 + NTSRPres=0] + 0x06, // Length + 0x11, 0x01, 0x02, 0x03, 0x04, 0x22, // STA Info : Local Sta Link 2 MAC address + // STA Profile + // Remaining STA Profile for Link 3 + 0x11, 0x15, 0x21, 0x02, 0x00, 0x0e, 0xff, 0x03, 0x38, 0x01, 0x30, 0x00, + + + // WDI_TLV_ASSOCIATION_RESPONSE_FRAME + 0x2F, 0x00, + 0x55, 0x00, + 0x01, 0x04, //Capability + 0x00, 0x00, //Status + 0x01, 0xC0, //Association ID + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, //Rates + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, //Extended Rates + 0xDD, 0x18, + 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x80, 0x00, 0x03, 0xA4, 0x00, 0x00, 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00, 0x62, 0x32, 0x2F, 0x00, //WMM settings + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x22, 0x22, 0x22, 0x22, 0x00, 0x01, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x22, 0x22, 0x22, 0x22, 0x00, 0x02, // STA Info : AP Link 2 MAC address + // STA Profile + + + // WDI_TLV_BEACON_FRAME + 0x30, 0x00, + 0x97, 0x00, + + 0x22, 0x02, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, // Timestamp + 0x01, 0x00, // Beacon Interval + 0x31, 0x04, // Capability + 0x00, 0x0e, // SSID + 'W', 'i', '-', 'F', 'i', ' ', '7', ' ', '-', ' ', 'D', 'T', '0', '2', + 0x01, 0x08, + 0x82, 0x84, 0x8B, 0x96, 0x24, 0x30, 0x48, 0x6C, // Supported Rates + 0x03, 0x01, + 0x06, // DSS Parameters + 0x05, 0x04, + 0x00, 0x01, 0x00, 0x00, // TIM + 0x2A, 0x01, + 0x00, // ERP + 0x2F, 0x01, + 0x00, // Reserved + 0xff, 0x23, // Multilink Extension Element + 0x6B, // Multilink Extension ID + 0x01, 0x10, // MultiLink Control ([Reserved=0000000 + MLDCapabilities=1 + 000 + LinkID=1 + Reserved=0 + Basic=000] = 0000000 1 000 1 0 000 = 0x0110) + 0x09, // Common Info length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x06, // AP MLD Mac address (required for Basic) + 0x01, // [ Link ID (1 octet) - in Beacon/ProbeResp/(Re)AssocResp frames ] + // [ BSS Parameters Change Count (1 octet) - from AP only ] + // [ Medium Synchronization delay (2 octets) - from AP only] + // [ EML Capabilities (2 octets) ] + 0x00, 0x03, // [ MLD Capabilities (2 octets) - (3 links max) in Beacon/ProbeResp/(Re)AssocReq/(Re)AssocResp frames ] + // Per-Sta profile - 1/2 (Link 2) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x22, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // STA Info : AP Link 1 MAC address + // STA Profile + // Per-Sta profile - 2/2 (Link 3) + 0x00, // Subelement ID = 0 for Per-Sta Profile Element + 0x09, // Length + 0x00, 0x23, // STA Control = (Reserved=00000+BSSParam=0+NTSRBS=0+NTSRLP=0+DTIM=0+BeaconInt=0+MAC=1+CompleteP=0+LinkID=0001) = 0x0021 + 0x00, // STA Info : Length + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // STA Info : AP Link 2 MAC address + // STA Profile + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x08, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x03, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0xc9, 0x14, // RNR IE + 0x04, 0x10, // TBTT: 0x04 => B2=1(FilteredAP),B4-B7=0(TBTT Information Count=0+1) :: 0x0c = TBTT Length + 0x51, 0x06, // Operating Class = 81 (2.4 GHz), Channel = 6 + 0x00, // TBTTOffset + 0x00, 0xA0, 0xB0, 0xC0, 0xD1, 0x09, // Bssid + 0x1d, 0xc5, 0x3b, 0x12, // ShortSsid + 0x40, // BssParameters + 0x00, // 20 MHz + 0x12, 0x07, 0x56, // Mld Parameters: MLD ID(8 bits) : LinkID (4 bits) + ... + 0x32, 0x04, + 0x0C, 0x12, 0x18, 0x60, // Extended Supported Rates + 0xDD, 0x09, + 0x00, 0x10, 0x18, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Vendor Specific + + // WDI_TLV_PHY_TYPE_LIST + 0x19, 0x00, + 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, // dot11_phy_type_eht + +}; + +//=============================================================================== +//=============================================================================== + +typedef struct +{ + UINT32 BandId; + WDI_MAC_ADDRESS* pMacAddress; + PUCHAR pTlvBssEntry; + UINT32 TlvBssEntrySize; + PUCHAR pTlvAssociationResult; + UINT32 TlvAssociationResultSize; + +} WdiTestConnectEntry, * PWdiTestConnectEntry; + +WdiTestConnectEntry g_ConnectEntries[] = +{ + // 0 + { // 0th Entry is disconnected state + 0, + nullptr, + nullptr, 0, + nullptr, 0, + }, + + // 1 - WFC_OPEN + { + WDI_BAND_ID_2400, + &s_Connect_Addr, + s_TLV_BSS_Entry_1, sizeof(s_TLV_BSS_Entry_1), + s_TLV_SuccessOpenAssociationResult, sizeof(s_TLV_SuccessOpenAssociationResult), + }, + + // 2 - WFC_OPEN + { + WDI_BAND_ID_2400, + &s_Connect_Addr_2_Open, + s_TLV_BSS_Entry_2_Open, sizeof(s_TLV_BSS_Entry_2_Open), + s_TLV_Success_AssociationResult_2_Open, sizeof(s_TLV_Success_AssociationResult_2_Open), + }, + + // 3 - WDI__WEP + { + WDI_BAND_ID_2400, + &s_Connect_Addr_3_WEP, + s_TLV_BSS_Entry_3_WEP, sizeof(s_TLV_BSS_Entry_3_WEP), + s_TLV_Success_AssociationResult_3_WEP, sizeof(s_TLV_Success_AssociationResult_3_WEP), + }, + + // 4 - WDI_SECURE + { + WDI_BAND_ID_2400, + &s_Connect_Addr_4_RSNA_CCMP, + s_TLV_BSS_Entry_4_RSNA_CCMP, sizeof(s_TLV_BSS_Entry_4_RSNA_CCMP), + s_TLV_Success_AssociationResult_4_RSNA_CCMP, sizeof(s_TLV_Success_AssociationResult_4_RSNA_CCMP), + }, + + // 5 - WDI__IHV + { + TESTMP_BAND_IHV, + &s_Connect_Addr_5_IHV, + s_TLV_BSS_Entry_5_IHV, sizeof(s_TLV_BSS_Entry_5_IHV), + s_TLV_Success_AssociationResult_5_IHV, sizeof(s_TLV_Success_AssociationResult_5_IHV), + }, + + // 6 - WDI__FT + { + WDI_BAND_ID_2400, + &s_Connect_Addr_6_FT_CCMP, + s_TLV_BSS_Entry_6_FT_CCMP, sizeof(s_TLV_BSS_Entry_6_FT_CCMP), + s_TLV_Success_AssociationResult_6_FT_CCMP, sizeof(s_TLV_Success_AssociationResult_6_FT_CCMP), + }, + + // 7 - WDI__FTPSK + { + WDI_BAND_ID_2400, + &s_Connect_Addr_7_FT_PSK_CCMP, + s_TLV_BSS_Entry_7_FT_PSK_CCMP, sizeof(s_TLV_BSS_Entry_7_FT_PSK_CCMP), + s_TLV_Success_AssociationResult_7_FT_PSK_CCMP, sizeof(s_TLV_Success_AssociationResult_7_FT_PSK_CCMP), + }, + + // 8 - + { + WDI_BAND_ID_2400, + &s_Connect_Addr_8_Hidden, + s_TLV_BSS_Entry_Beacon_8_Hidden, sizeof(s_TLV_BSS_Entry_Beacon_8_Hidden), + s_TLV_Success_AssociationResult_8_Hidden, sizeof(s_TLV_Success_AssociationResult_8_Hidden), + }, + + // 9 - WDI_adPSK + { + WDI_BAND_ID_60000, + &s_Connect_Addr_9_11ad_PSK, + s_TLV_BSS_Entry_9_11ad_ProbeResponse_PSK, sizeof(s_TLV_BSS_Entry_9_11ad_ProbeResponse_PSK), + s_TLV_Success_AssociationResult_9_11ad_PSK, sizeof(s_TLV_Success_AssociationResult_9_11ad_PSK), + }, + + // 10 - WDI_ad_1x + { + WDI_BAND_ID_60000, + &s_Connect_Addr_10_11ad_1x, + s_TLV_BSS_Entry_10_11ad_ProbeResponse_1x, sizeof(s_TLV_BSS_Entry_10_11ad_ProbeResponse_1x), + s_TLV_Success_AssociationResult_10_11ad_1x, sizeof(s_TLV_Success_AssociationResult_10_11ad_1x), + }, + + // 11 - WDI_ad_ON + { + WDI_BAND_ID_60000, + &s_Connect_Addr_11_11ad_Open, + s_TLV_BSS_Entry_11_11ad_ProbeResponse_Open, sizeof(s_TLV_BSS_Entry_11_11ad_ProbeResponse_Open), + s_TLV_Success_AssociationResult_11_11ad_Open, sizeof(s_TLV_Success_AssociationResult_11_11ad_Open), + }, + + // 12 - WDI_OPEN_11ax.2.4 + { + WDI_BAND_ID_60000, + &s_Connect_Addr_12_11ax_24_Open, + s_TLV_BSS_Entry_12_11ax_24_Open, sizeof(s_TLV_BSS_Entry_12_11ax_24_Open), + s_TLV_Success_AssociationResult_12_11ax_24_Open, sizeof(s_TLV_Success_AssociationResult_12_11ax_24_Open), + }, + + // 13 - WDI_OPEN_11ax.5 + { + WDI_BAND_ID_5000, + &s_Connect_Addr_13_11ax_5_Open, + s_TLV_BSS_Entry_13_11ax_5_Open, sizeof(s_TLV_BSS_Entry_13_11ax_5_Open), + s_TLV_Success_AssociationResult_13_11ax_5_Open, sizeof(s_TLV_Success_AssociationResult_13_11ax_5_Open), + }, + + // 14 - WDI_WPA3-SAE + { + WDI_BAND_ID_2400, + &s_Connect_Addr_14_WPA3_SAE_CCMP, + s_TLV_BSS_Entry_14_WPA3_SAE_CCMP, sizeof(s_TLV_BSS_Entry_14_WPA3_SAE_CCMP), + s_TLV_Success_AssociationResult_14_WPA3_SAE_CCMP, sizeof(s_TLV_Success_AssociationResult_14_WPA3_SAE_CCMP), + }, + + // 15 - WDI_SHA256 + { + WDI_BAND_ID_2400, + &s_Connect_Addr_15_WPA2PSK_SHA256, + s_TLV_BSS_Entry_15_WPA2PSK_SHA256, sizeof(s_TLV_BSS_Entry_15_WPA2PSK_SHA256), + s_TLV_Success_AssociationResult_15_WPA2PSK_SHA256, sizeof(s_TLV_Success_AssociationResult_15_WPA2PSK_SHA256), + }, + + // 16 - WDI_WPA3-SUITE_B + { + WDI_BAND_ID_2400, + &s_Connect_Addr_16_WPA3_SUITEB, + s_TLV_BSS_Entry_16_WPA3_SUITEB, sizeof(s_TLV_BSS_Entry_16_WPA3_SUITEB), + s_TLV_Success_AssociationResult_16_WPA3_SUITEB, sizeof(s_TLV_Success_AssociationResult_16_WPA3_SUITEB), + }, + + // 17 - 6E__1 + { + WDI_BAND_ID_2400, + &s_Connect_Addr_17_6G_S1_2_4_Ghz, + s_TLV_BSS_Entry_17_6G_S1_2_4_Ghz, sizeof(s_TLV_BSS_Entry_17_6G_S1_2_4_Ghz), + s_TLV_Success_AssociationResult_17_6G_S1_2_4_Ghz, sizeof(s_TLV_Success_AssociationResult_17_6G_S1_2_4_Ghz), + }, + + // 18 - 6E__1 + { + WDI_BAND_ID_5000, + &s_Connect_Addr_18_6G_S1_5_Ghz, + s_TLV_BSS_Entry_18_6G_S1_5_Ghz, sizeof(s_TLV_BSS_Entry_18_6G_S1_5_Ghz), + s_TLV_Success_AssociationResult_18_6G_S1_5_Ghz, sizeof(s_TLV_Success_AssociationResult_18_6G_S1_5_Ghz), + }, + + // 19 - 6E__1 + { + WDI_BAND_ID_6000, + &s_Connect_Addr_19_6G_S1a_6_Ghz, + s_TLV_BSS_Entry_19_6G_S1a_6_Ghz, sizeof(s_TLV_BSS_Entry_19_6G_S1a_6_Ghz), + s_TLV_Success_AssociationResult_19_6G_S1a_6_Ghz, sizeof(s_TLV_Success_AssociationResult_19_6G_S1a_6_Ghz), + }, + + // 20 - 6E__1 + { + WDI_BAND_ID_6000, + &s_Connect_Addr_20_6G_S1b_6_Ghz, + s_TLV_BSS_Entry_20_6G_S1b_6_Ghz, sizeof(s_TLV_BSS_Entry_20_6G_S1b_6_Ghz), + s_TLV_Success_AssociationResult_20_6G_S1b_6_Ghz, sizeof(s_TLV_Success_AssociationResult_20_6G_S1b_6_Ghz), + }, + + // 21 - 6E__2 + { + WDI_BAND_ID_2400, + &s_Connect_Addr_21_6G_S2_2_4_Ghz, + s_TLV_BSS_Entry_21_6G_S2_2_4_Ghz, sizeof(s_TLV_BSS_Entry_21_6G_S2_2_4_Ghz), + s_TLV_Success_AssociationResult_21_6G_S2_2_4_Ghz, sizeof(s_TLV_Success_AssociationResult_21_6G_S2_2_4_Ghz), + }, + + // 22 - 6E__2 + { + WDI_BAND_ID_5000, + &s_Connect_Addr_22_6G_S2_5_Ghz, + s_TLV_BSS_Entry_22_6G_S2_5_Ghz, sizeof(s_TLV_BSS_Entry_22_6G_S2_5_Ghz), + s_TLV_Success_AssociationResult_22_6G_S2_5_Ghz, sizeof(s_TLV_Success_AssociationResult_22_6G_S2_5_Ghz), + }, + + // 23 - 6E__2 + { + WDI_BAND_ID_6000, + &s_Connect_Addr_23_6G_S2_6_Ghz, + s_TLV_BSS_Entry_23_6G_S2_6_Ghz, sizeof(s_TLV_BSS_Entry_23_6G_S2_6_Ghz), + s_TLV_Success_AssociationResult_23_6G_S2_6_Ghz, sizeof(s_TLV_Success_AssociationResult_23_6G_S2_6_Ghz), + }, + + // 24 - 6E__3 + { + WDI_BAND_ID_2400, + &s_Connect_Addr_24_6G_S3_2_4_Ghz, + s_TLV_BSS_Entry_24_6G_S3_2_4_Ghz, sizeof(s_TLV_BSS_Entry_24_6G_S3_2_4_Ghz), + s_TLV_Success_AssociationResult_24_6G_S3_2_4_Ghz, sizeof(s_TLV_Success_AssociationResult_24_6G_S3_2_4_Ghz), + }, + + // 25 - 6E__4 + { + WDI_BAND_ID_6000, + &s_Connect_Addr_25_6G_S4_6_Ghz, + s_TLV_BSS_Entry_25_6G_S4_6_Ghz, sizeof(s_TLV_BSS_Entry_25_6G_S4_6_Ghz), + s_TLV_Success_AssociationResult_25_6G_S4_6_Ghz, sizeof(s_TLV_Success_AssociationResult_25_6G_S4_6_Ghz), + }, + + // 26 - WDI_OWE_RNR + { + WDI_BAND_ID_2400, + &s_ConnectAddr_26_OWE_With_RNR, + s_TLV_BSS_Entry_26_OWE_With_RNR, sizeof(s_TLV_BSS_Entry_26_OWE_With_RNR), + s_TLV_Failure_AssociationResult_26_OWE_With_RNR, sizeof(s_TLV_Failure_AssociationResult_26_OWE_With_RNR) + }, + // 27 - <WDI_OWE_TM_OPEN> + { + WDI_BAND_ID_2400, + &s_ConnectAddr_27_OWE_TM_OWE, + s_TLV_BSS_Entry_27_OWE_TM_OWE, sizeof(s_TLV_BSS_Entry_27_OWE_TM_OWE), + s_TLV_Failure_AssociationResult_27_OWE_TM_OWE, sizeof(s_TLV_Failure_AssociationResult_27_OWE_TM_OWE) + }, + // 28 - WDI_OWE_TM_OPEN + { + WDI_BAND_ID_2400, + &s_ConnectAddr_28_OWE_TM_Open, + s_TLV_BSS_Entry_28_OWE_TM_Open_Beacon, sizeof(s_TLV_BSS_Entry_28_OWE_TM_Open_Beacon), + s_TLV_Failure_AssociationResult_28_OWE_TM_Open, sizeof(s_TLV_Failure_AssociationResult_28_OWE_TM_Open) + }, + + // 29 is only MLD address for Wi-Fi 7 + // 30 - Wi-Fi 7 - Mixed + { + WDI_BAND_ID_5000, + &s_Connect_Addr_30_WiFi7_Mixed_Link_1, + s_TLV_BSS_Entry_30_WiFi7_Mixed_Link_1, sizeof(s_TLV_BSS_Entry_30_WiFi7_Mixed_Link_1), + s_TLV_Success_AssociationResult_30_WiFi7_Mixed_Link_1, sizeof(s_TLV_Success_AssociationResult_30_WiFi7_Mixed_Link_1), + }, + // 34 - Wi-Fi 7 - Open + { + WDI_BAND_ID_5000, + &s_Connect_Addr_34_WiFi7_Open_Link_1, + s_TLV_BSS_Entry_34_WiFi7_Open_Link_1, sizeof(s_TLV_BSS_Entry_34_WiFi7_Open_Link_1), + s_TLV_Success_AssociationResult_34_WiFi7_Open_Link_1, sizeof(s_TLV_Success_AssociationResult_34_WiFi7_Open_Link_1), + }, + // 38 - Wi-Fi 7 - Only + { + WDI_BAND_ID_6000, + &s_Connect_Addr_38_WiFi7_Only_Link_1, + s_TLV_BSS_Entry_38_WiFi7_Only_Link_1, sizeof(s_TLV_BSS_Entry_38_WiFi7_Only_Link_1), + s_TLV_Success_AssociationResult_38_WiFi7_Only_Link_1, sizeof(s_TLV_Success_AssociationResult_38_WiFi7_Only_Link_1), + }, + + // 41 - Dual-Sta + { + WDI_BAND_ID_5000, + &s_Connect_Addr_41_DualSta_5Ghz, + s_TLV_BSS_Entry_41_DualSta_5Ghz, sizeof(s_TLV_BSS_Entry_41_DualSta_5Ghz), + s_TLV_SuccessOpenAssociationResult_41_DualSta_5Ghz, sizeof(s_TLV_SuccessOpenAssociationResult_41_DualSta_5Ghz), + }, + + // 42 - Dual-Sta + { + WDI_BAND_ID_6000, + &s_Connect_Addr_42_DualSta_6Ghz, + s_TLV_BSS_Entry_42_DualSta_6Ghz, sizeof(s_TLV_BSS_Entry_42_DualSta_6Ghz), + s_TLV_SuccessOpenAssociationResult_42_DualSta_6Ghz, sizeof(s_TLV_SuccessOpenAssociationResult_42_DualSta_6Ghz), + }, + + // 43 - Speed Test(01) + { + WDI_BAND_ID_5000, + &s_Connect_Addr_43_Speed_01_WiFi7_Open_Link_1, + s_TLV_BSS_Entry_43_WiFi7_Open_Link_1, sizeof(s_TLV_BSS_Entry_43_WiFi7_Open_Link_1), + s_TLV_Success_AssociationResult_43_WiFi7_Open_Link_1, sizeof(s_TLV_Success_AssociationResult_43_WiFi7_Open_Link_1), + }, + + // 44 - Speed Test(02) + { + WDI_BAND_ID_5000, + &s_Connect_Addr_44_Speed_02_WiFi7_Open_Link_1, + s_TLV_BSS_Entry_44_WiFi7_Open_Link_1, sizeof(s_TLV_BSS_Entry_44_WiFi7_Open_Link_1), + s_TLV_Success_AssociationResult_44_WiFi7_Open_Link_1, sizeof(s_TLV_Success_AssociationResult_44_WiFi7_Open_Link_1), + }, +}; + +// clang-format on diff --git a/network/wlan/wificx/drivercode/wifirequest.cpp b/network/wlan/wificx/drivercode/wifirequest.cpp new file mode 100644 index 00000000..c84c1d97 --- /dev/null +++ b/network/wlan/wificx/drivercode/wifirequest.cpp @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +#include "precomp.h" +#include "wifitransition.h" +#include "wifirequest.h" +#include "wifirequest.tmh" + +_Use_decl_annotations_ +void EvtWifiDeviceSendCommand(WDFDEVICE Device, WIFIREQUEST SendRequest) +{ + UINT InBufferLen = 0; + UINT OutBufferLen = 0; + void* Buffer = WifiRequestGetInOutBuffer(SendRequest, &InBufferLen, &OutBufferLen); + UINT16 MessageId = WifiRequestGetMessageId(SendRequest); + + TransitionContext tctx{ + Device, + WifiGetIhvDeviceContext(Device), + SendRequest, + static_cast<PWDI_MESSAGE_HEADER>(Buffer), + Buffer, + InBufferLen, + OutBufferLen + }; + + if(!NT_SUCCESS(RunTransitionByMessage(tctx, MessageId))) + { + WFCError("RunTransitionByMessage failed for MessageId: 0x%04X", MessageId); + return; + } +} + +void WifiIhvSendIndicationToOs( + _In_ WDFDEVICE Device, + _In_ const PWDI_MESSAGE_HEADER pOriginalWdiHeader, + _In_ UINT16 WifiRequestMessageId, + _In_ UINT32 WifiRequestTransactionId, + _In_ NTSTATUS WifiRquestM4Status, + _In_opt_bytecount_(TlvDataSize) PUCHAR pTlvData, + _In_ UINT32 TlvDataSize) +{ + WDFMEMORY data = WDF_NO_HANDLE; + PUCHAR pIndicationBuffer = nullptr; + PWDI_MESSAGE_HEADER pIndicationHeader = nullptr; + SIZE_T indicationSize = sizeof(WDI_MESSAGE_HEADER) + TlvDataSize; + WDF_OBJECT_ATTRIBUTES objectAttribs; + + WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); + objectAttribs.ParentObject = Device; + + if(!NT_SUCCESS(WdfMemoryCreate(&objectAttribs, NonPagedPoolNx, 0, indicationSize, &data, reinterpret_cast<void**>(&pIndicationBuffer)))) + { + WFCError("Failed to create indication buffer"); + return; + } + + RtlZeroMemory(pIndicationBuffer, indicationSize); + pIndicationHeader = reinterpret_cast<PWDI_MESSAGE_HEADER>(pIndicationBuffer); + pIndicationHeader->PortId = pOriginalWdiHeader->PortId; + pIndicationHeader->Reserved = pOriginalWdiHeader->Reserved; + pIndicationHeader->Status = Wifi::ConvertNDISSTATUSToNTSTATUS(WifiRquestM4Status); + pIndicationHeader->TransactionId = WifiRequestTransactionId; + pIndicationHeader->IhvSpecificId = pOriginalWdiHeader->IhvSpecificId; + + if (TlvDataSize > 0 && pTlvData != nullptr) + { + RtlCopyMemory(pIndicationBuffer + sizeof(WDI_MESSAGE_HEADER), pTlvData, TlvDataSize); + } + + // Send the indication up to WifiCx + WifiDeviceReceiveIndication(Device, WifiRequestMessageId, data); + + // Don't need to keep this around + WdfObjectDelete(data); +} + +_Use_decl_annotations_ +void WifiIhvSendUnsolicitedIndicationToOs(WDFDEVICE Device, PWDI_MESSAGE_HEADER pWdiHeader, UINT16 MessageId, PUCHAR pTlvData, UINT32 TlvDataSize) +{ + WifiIhvSendIndicationToOs(Device, pWdiHeader, MessageId, 0, STATUS_SUCCESS, pTlvData, TlvDataSize); //TransactionId required to be 0 for unsolicited indications. +} +_Use_decl_annotations_ +void WifiIhvNotifyM3Completion(WIFIREQUEST Request, NTSTATUS WifiRequestM3Status, UINT BytesWritten) +{ + if(!NT_SUCCESS(WifiRequestM3Status)) + { + WFCError("WifiRequest M3 failed: %!STATUS!, BytesWritten: %d\n", WifiRequestM3Status, BytesWritten); + } + // Report the M3 status back to OS + // OS expects M3 before the M4 + WifiRequestComplete(Request, WifiRequestM3Status, BytesWritten); +} + +_Use_decl_annotations_ +void WifiIhvSendM4IndicationToOs(WDFDEVICE Device, UINT16 WifiRequestMessageId, const PWDI_MESSAGE_HEADER pWdiHeader, NTSTATUS WifiRequestM4Status) +{ + WifiIhvSendIndicationToOs(Device, pWdiHeader, WifiRequestMessageId, pWdiHeader->TransactionId, WifiRequestM4Status, nullptr, 0); +} diff --git a/network/wlan/wificx/drivercode/wifirequest.h b/network/wlan/wificx/drivercode/wifirequest.h new file mode 100644 index 00000000..74380548 --- /dev/null +++ b/network/wlan/wificx/drivercode/wifirequest.h @@ -0,0 +1,23 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once +#include "device.h" + +EVT_WIFI_DEVICE_SEND_COMMAND EvtWifiDeviceSendCommand; + +void WifiIhvSendUnsolicitedIndicationToOs( + _In_ WDFDEVICE Device, + _In_ PWDI_MESSAGE_HEADER pWdiHeader, + _In_ UINT16 MessageId, + _In_opt_bytecount_(TlvDataSize) PUCHAR pTlvData, + _In_ UINT32 TlvDataSize); + +void WifiIhvNotifyM3Completion( + _In_ WIFIREQUEST Request, + _In_ NTSTATUS WifiRequestM3Status, + _In_ UINT BytesWritten); + +void WifiIhvSendM4IndicationToOs( + _In_ WDFDEVICE Device, + _In_ UINT16 WifiRequestMessageId, + _In_ const PWDI_MESSAGE_HEADER pOriginalWdiHeader, + _In_ NTSTATUS WifiRequestM4Status);
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/wifitransition.cpp b/network/wlan/wificx/drivercode/wifitransition.cpp new file mode 100644 index 00000000..2e1b7ef2 --- /dev/null +++ b/network/wlan/wificx/drivercode/wifitransition.cpp @@ -0,0 +1,466 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. + +#include "wifitransition.h" + +// Common TLV parsing helper: computes TLV span, optional dump, calls a parser, converts status. +template<typename Param, typename ParserFn> +NTSTATUS ParseTlvCommon(TransitionContext& ctx, + UINT16 messageId, + ParserFn parser, + Param& outParams, + bool dumpStream = true) +{ + if (ctx.InLen < sizeof(WDI_MESSAGE_HEADER)) + { + return STATUS_INVALID_PARAMETER; + } + + auto* tlvBytes = static_cast<UCHAR*>(ctx.RawBuffer) + sizeof(WDI_MESSAGE_HEADER); + auto tlvLen = static_cast<ULONG>(ctx.InLen - sizeof(WDI_MESSAGE_HEADER)); + + if (dumpStream) + { + DumpMessageTlvByteStream( + messageId, + TRUE, + ctx.DevCtx->TlvContext.PeerVersion, + tlvLen, + tlvBytes, + 0, + nullptr); + } + + auto ndisStatus = parser(tlvLen, tlvBytes, &ctx.DevCtx->TlvContext, &outParams); + return Wifi::ConvertNDISSTATUSToNTSTATUS(ndisStatus); +} + + +// Primary traits template (specialize per MessageId) +template<UINT16 MsgId> +struct TransitionTraits; + +// --- Generic pure-type traits template (add before existing specializations) --- +// WIFIREQUEST always needs M3 notification, so TPreM3Fn is mandatory. +// and WIFICX expectes the M3 then M4 order, so we always execute M3 then M4. +// using template parameters to configure parsing, cleanup, M3/M4 steps. +// to make sure that all transitions have consistent implementations. +template< + UINT16 TMsgId, + typename TParam, + UINT16 TCompleteIndication, + bool TDumpTlvStream, + NDIS_STATUS (*TParseFn)(ULONG, const UINT8*, PCTLV_CONTEXT, TParam*), + void (*TCleanupFn)(TParam*), + NTSTATUS (WifiHAL::*TPreM3Fn)(), // mandatory pre-M3 hook + NTSTATUS (WifiHAL::*THalM3Fn)(const TParam&, const PWDI_MESSAGE_HEADER, UINT BytesWriten), // optional HAL M3 (may be nullptr) + NTSTATUS (WifiHAL::*TPreM4Fn)(), // optional pre-M4 hook (may be nullptr) + NTSTATUS (WifiHAL::*THalM4Fn)(const PWDI_MESSAGE_HEADER) // optional HAL M4 (may be nullptr) +> +struct GenericTransitionTraits +{ + using ParamType = TParam; + enum : UINT16 { CompleteIndication = TCompleteIndication }; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + if (ctx.InLen < sizeof(WDI_MESSAGE_HEADER)) + { + return STATUS_INVALID_PARAMETER; + } + + auto* tlvBytes = static_cast<UCHAR*>(ctx.RawBuffer) + sizeof(WDI_MESSAGE_HEADER); + auto tlvLen = static_cast<ULONG>(ctx.InLen - sizeof(WDI_MESSAGE_HEADER)); + + if (TDumpTlvStream) + { + DumpMessageTlvByteStream( + TMsgId, + TRUE, + ctx.DevCtx->TlvContext.PeerVersion, + tlvLen, + tlvBytes, + 0, + nullptr); + } + + auto ndisStatus = TParseFn(tlvLen, tlvBytes, &ctx.DevCtx->TlvContext, &p); + return Wifi::ConvertNDISSTATUSToNTSTATUS(ndisStatus); + } + + void Cleanup(ParamType& p) { TCleanupFn(&p); } + + // Make static so pointer matches ExecuteSteps expected callable type (no implicit this) + static NTSTATUS StepM3(TransitionContext& c, ParamType& p, UINT& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + ASSERT(TPreM3Fn); + + if (TPreM3Fn) + { + // Call member function pointer on WifiHAL instance + NTSTATUS preStatus = (GetWifiHalFromHandle(c.DevCtx->WdfDevice)->*TPreM3Fn)(); + if (!NT_SUCCESS(preStatus)) + { + return preStatus; + } + } + + if (THalM3Fn) + { + // Pass required third argument (BytesWriten) to HAL M3 function + return (GetWifiHalFromHandle(c.DevCtx->WdfDevice)->*THalM3Fn)(p, c.Header, bytesWritten); + } + + return STATUS_SUCCESS; + } + + static NTSTATUS StepM4(TransitionContext& c, ParamType&) + { + if (TPreM4Fn) + { + NTSTATUS preStatus = (GetWifiHalFromHandle(c.DevCtx->WdfDevice)->*TPreM4Fn)(); + if (!NT_SUCCESS(preStatus)) + { + return preStatus; + } + } + + if (THalM4Fn) + { + return (GetWifiHalFromHandle(c.DevCtx->WdfDevice)->*THalM4Fn)(c.Header); + } + + return (TPreM4Fn == nullptr && THalM4Fn == nullptr) ? STATUS_PENDING : STATUS_SUCCESS; + } + + NTSTATUS Handle(TransitionContext& ctx, ParamType& p) + { + return ExecuteSteps(ctx, p, &GenericTransitionTraits::StepM3, &GenericTransitionTraits::StepM4); + } + + bool ShouldSendComplete(NTSTATUS s) const { return s != STATUS_PENDING; } +}; + +// Execute two step callables. +// StepM3Fn signature: NTSTATUS (TransitionContext&, Param&, UINT& bytesWritten) +// StepM4Fn signature: NTSTATUS (TransitionContext&, Param&) +// Always calls WifiRequestComplete after StepM3 with the bytesWritten produced by StepM3. +// Skips StepM4 if StepM3 failed +template<typename Param, typename StepM3Fn, typename StepM4Fn> +NTSTATUS ExecuteSteps(TransitionContext& ctx, Param& p, StepM3Fn stepM3, StepM4Fn stepM4) +{ + UINT bytesWritten = sizeof(WDI_MESSAGE_HEADER); // default minimum + NTSTATUS m3Status = stepM3(ctx, p, bytesWritten); + // Report the M3 status back to OS + // OS expects M3 before the M4 + WifiIhvNotifyM3Completion(ctx.WifiRequest, m3Status, bytesWritten); + if (!NT_SUCCESS(m3Status)) + { + return m3Status; + } + return stepM4(ctx, p); +} + +// -------- Generic runner (compile-time) -------- +template<UINT16 MsgId> +NTSTATUS RunTransition(TransitionContext& ctx) +{ + TransitionTraits<MsgId> traits; + typename TransitionTraits<MsgId>::ParamType params{}; + NTSTATUS parseStatus = traits.Parse(ctx, params); + if (!NT_SUCCESS(parseStatus)) + { + traits.Cleanup(params); + // Report Failed M3 to OS + // Note: No M4 indication on parse failure + WifiIhvNotifyM3Completion(ctx.WifiRequest, parseStatus, 0); + return parseStatus; + } + + NTSTATUS m4Status = traits.Handle(ctx, params); + + if (traits.ShouldSendComplete(m4Status)) + { + WifiIhvSendM4IndicationToOs( + ctx.Device, + TransitionTraits<MsgId>::CompleteIndication, + ctx.Header, + m4Status); + } + + traits.Cleanup(params); + return m4Status; +} + +// ============================================================================ +// Property GET/SET messages (single M3 completion) +// ---------------------------------------------------------------------------- +// Unlike the M3/M4 task flow above, a property GET/SET is a single M3 step that +// returns its result synchronously in the request's in/out buffer. The HAL +// handler writes the response TLV stream and reports the real number of bytes +// written (by reference); the request is completed (M3) with that length. +// No M4 indication. +// ============================================================================ +template< + UINT16 TMsgId, + typename TParam, + bool TDumpTlvStream, + NDIS_STATUS (*TParseFn)(ULONG, const UINT8*, PCTLV_CONTEXT, TParam*), + void (*TCleanupFn)(TParam*), + NTSTATUS (WifiHAL::*TPreFn)(), // optional pre-check hook (may be nullptr) + NTSTATUS (WifiHAL::*TPropertyFn)(const TParam&, void*, ULONG, ULONG&) // mandatory property HAL handler +> +struct PropertyM3Traits +{ + using ParamType = TParam; + + NTSTATUS Parse(TransitionContext& ctx, ParamType& p) + { + if (ctx.InLen < sizeof(WDI_MESSAGE_HEADER)) + { + return STATUS_INVALID_PARAMETER; + } + + auto* tlvBytes = static_cast<UCHAR*>(ctx.RawBuffer) + sizeof(WDI_MESSAGE_HEADER); + auto tlvLen = static_cast<ULONG>(ctx.InLen - sizeof(WDI_MESSAGE_HEADER)); + + if (TDumpTlvStream) + { + DumpMessageTlvByteStream(TMsgId, TRUE, ctx.DevCtx->TlvContext.PeerVersion, tlvLen, tlvBytes, 0, nullptr); + } + + auto ndisStatus = TParseFn(tlvLen, tlvBytes, &ctx.DevCtx->TlvContext, &p); + return Wifi::ConvertNDISSTATUSToNTSTATUS(ndisStatus); + } + + void Cleanup(ParamType& p) { TCleanupFn(&p); } + + // Runs the optional pre-check then the property handler. The handler writes the + // out-buffer and reports the number of bytes written. + NTSTATUS Handle(TransitionContext& ctx, ParamType& p, ULONG& bytesWritten) + { + bytesWritten = sizeof(WDI_MESSAGE_HEADER); + + WifiHAL* hal = GetWifiHalFromHandle(ctx.Device); + + if (TPreFn) + { + NTSTATUS preStatus = (hal->*TPreFn)(); + if (!NT_SUCCESS(preStatus)) + { + return preStatus; + } + } + + return (hal->*TPropertyFn)(p, ctx.RawBuffer, ctx.OutLen, bytesWritten); + } +}; + +// Primary traits template for property GET/SET messages (specialize per MessageId) +template<UINT16 MsgId> +struct PropertyTraits; + +// Generic runner for property GET/SET messages: parse -> handle -> complete (M3). +// Completes the request synchronously with the number of bytes the HAL wrote. +template<UINT16 MsgId> +NTSTATUS RunPropertyM3(TransitionContext& ctx) +{ + PropertyTraits<MsgId> traits; + typename PropertyTraits<MsgId>::ParamType params{}; + + NTSTATUS status = traits.Parse(ctx, params); + if (!NT_SUCCESS(status)) + { + traits.Cleanup(params); + WifiRequestComplete(ctx.WifiRequest, status, sizeof(WDI_MESSAGE_HEADER)); + return status; + } + + ULONG bytesWritten = sizeof(WDI_MESSAGE_HEADER); + status = traits.Handle(ctx, params, bytesWritten); + + traits.Cleanup(params); + WifiRequestComplete(ctx.WifiRequest, status, bytesWritten); + return status; +} + +//// -------- SCENARIO: [Connect with a SAE WI-FI7 network -------- +/// Demo: Handle WDI_TASK_CONNECT + WDI_SET_SAE_AUTH_PARAMS then WDI_TASK_DISCONNECT +/// Scope: +/// -WifiRequest WDI_TASK_CONNECT & WDI_TASK_DISCONNECT are both WIFICX task commands, which is a two step M3/M4 transition +/// -The direct WifiRequest WDI_SET_SAE_AUTH_PARAMS, which is a single step transition but +/// is logically part of the connect scenario. since WDI_SET_SAE_AUTH_PARAMS is WIFICX property command, +/// it only has M3 step, no M4 step. +/// - The WifiCx unsolicited indication e.g. WDI_INDICATION_SAE_AUTH_PARAMS_NEEDED is sent from the HAL during the connect process, +/// Notes: +/// - M3 and M4 status mainly used for WifiCx to track progress of the transition. e.g. the hung detection and trigger recovery. +/// - The actual scenario result is reported through unsolicited indication. +/// + +// -------- WDI_TASK_CONNECT -------- +template<> +struct TransitionTraits<WDI_TASK_CONNECT> + : GenericTransitionTraits < + WDI_TASK_CONNECT, + WDI_TASK_CONNECT_PARAMETERS, + WDI_INDICATION_CONNECT_COMPLETE, + true, // dump TLV stream? (was true in original) + ParseWdiTaskConnect, + CleanupParsedWdiTaskConnect, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvConnect, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr + > +{ +}; + +// --- WDI_SET_SAE_AUTH_PARAMS --- +template<> +struct TransitionTraits<WDI_SET_SAE_AUTH_PARAMS> + : GenericTransitionTraits< + WDI_SET_SAE_AUTH_PARAMS, + WDI_SET_SAE_AUTH_PARAMS_COMMAND, + WDI_INDICATION_CONNECT_COMPLETE, + false, // dump TLV stream? (was false in original) + ParseWdiSetSaeAuthParams, + CleanupParsedWdiSetSaeAuthParams, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvSetSaeAuthParams, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr// HAL M4 + > +{}; + +// -------- WDI_TASK_DISCONNECT -------- +template<> +struct TransitionTraits<WDI_TASK_DISCONNECT> + : GenericTransitionTraits< + WDI_TASK_DISCONNECT, + WDI_TASK_DISCONNECT_PARAMETERS, + WDI_INDICATION_DISCONNECT_COMPLETE, + false, // dump TLV stream? (was false in original) + ParseWdiTaskDisconnect, + CleanupParsedWdiTaskDisconnect, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvDisconnect, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr // HAL M4 + > +{ +}; +/// ----- End of scenario [Connect with a SAE WI-FI7 network]----- + +// -------- WDI_TASK_DOT11_RESET -------- +template<> +struct TransitionTraits<WDI_TASK_DOT11_RESET> + : GenericTransitionTraits < + WDI_TASK_DOT11_RESET, + WDI_TASK_DOT11_RESET_PARAMETERS, + WDI_INDICATION_DOT11_RESET_COMPLETE, + false, // dump TLV stream? (was false in original) + ParseWdiTaskDot11Reset, + CleanupParsedWdiTaskDot11Reset, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvReset, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr // HAL M4 + > +{ +}; + +// -------- WDI_TASK_SCAN -------- +template<> +struct TransitionTraits<WDI_TASK_SCAN> + : GenericTransitionTraits < + WDI_TASK_SCAN, + WDI_SCAN_PARAMETERS, + WDI_INDICATION_SCAN_COMPLETE, + true, // dump TLV stream? (was true in original) + ParseWdiTaskScan, + CleanupParsedWdiTaskScan, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvScan, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr // HAL M4 + > +{ +}; + +// -------- WDI_TASK_SET_RADIO_STATE -------- +template<> +struct TransitionTraits<WDI_TASK_SET_RADIO_STATE> + : GenericTransitionTraits < + WDI_TASK_SET_RADIO_STATE, + WDI_SET_RADIO_STATE_PARAMETERS, + WDI_INDICATION_SET_RADIO_STATE_COMPLETE, + true, // dump TLV stream? (was true in original) + ParseWdiTaskSetRadioState, + CleanupParsedWdiTaskSetRadioState, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-M3 + &WifiHAL::WifiIhvSetRadioState, // HAL M3 + &WifiHAL::WifiIhvGetPendingTransitionStatus, // pre-M4 + nullptr // HAL M4 + > +{ +}; + +// -------- WDI_GET_SUPPORTED_DEVICE_SERVICES (property GET) -------- +// Request body is empty (header sufficient); the HAL produces the +// WDI_TLV_DEVICE_SERVICE_GUID_LIST result into the out-buffer. +template<> +struct PropertyTraits<WDI_GET_SUPPORTED_DEVICE_SERVICES> + : PropertyM3Traits< + WDI_GET_SUPPORTED_DEVICE_SERVICES, + WDI_GET_SUPPORTED_DEVICE_SERVICES_INPUTS, + true, // dump TLV stream + ParseWdiGetSupportedDeviceServices, + CleanupParsedWdiGetSupportedDeviceServices, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-check + &WifiHAL::WifiIhvGetSupportedDeviceServices // property handler + > +{}; + +// -------- WDI_DEVICE_SERVICE_COMMAND (property SET/GET) -------- +// Reads the request data blob (WDI_TLV_DEVICE_SERVICE_PARAMS_*) and the HAL writes +// the response data blob into the out-buffer. +template<> +struct PropertyTraits<WDI_DEVICE_SERVICE_COMMAND> + : PropertyM3Traits< + WDI_DEVICE_SERVICE_COMMAND, + WDI_DEVICE_SERVICE_COMMAND_INPUTS, + true, // dump TLV stream + ParseWdiDeviceServiceCommand, + CleanupParsedWdiDeviceServiceCommand, + &WifiHAL::WifiIhvIsDeviceReadyForRequest, // pre-check + &WifiHAL::WifiIhvDeviceServiceCommand // property handler + > +{}; + +// Runtime dispatcher switches on MessageId and invokes the matching compile-time runner. +NTSTATUS RunTransitionByMessage(TransitionContext& ctx, UINT16 messageId) +{ + switch (messageId) + { + case WDI_TASK_SET_RADIO_STATE: + return RunTransition<WDI_TASK_SET_RADIO_STATE>(ctx); + case WDI_TASK_SCAN: + return RunTransition<WDI_TASK_SCAN>(ctx); + case WDI_TASK_DOT11_RESET: + return RunTransition<WDI_TASK_DOT11_RESET>(ctx); + case WDI_TASK_CONNECT: + return RunTransition<WDI_TASK_CONNECT>(ctx); + case WDI_TASK_DISCONNECT: + return RunTransition<WDI_TASK_DISCONNECT>(ctx); + case WDI_SET_SAE_AUTH_PARAMS: + return RunTransition<WDI_SET_SAE_AUTH_PARAMS>(ctx); + case WDI_GET_SUPPORTED_DEVICE_SERVICES: + return RunPropertyM3<WDI_GET_SUPPORTED_DEVICE_SERVICES>(ctx); + case WDI_DEVICE_SERVICE_COMMAND: + return RunPropertyM3<WDI_DEVICE_SERVICE_COMMAND>(ctx); + default: + UINT bytesWritten = sizeof(WDI_MESSAGE_HEADER); + WifiRequestComplete(ctx.WifiRequest, STATUS_NOT_SUPPORTED, bytesWritten); + return STATUS_NOT_SUPPORTED; + } +}
\ No newline at end of file diff --git a/network/wlan/wificx/drivercode/wifitransition.h b/network/wlan/wificx/drivercode/wifitransition.h new file mode 100644 index 00000000..c48d4a78 --- /dev/null +++ b/network/wlan/wificx/drivercode/wifitransition.h @@ -0,0 +1,20 @@ +// Copyright (C) Microsoft Corporation. All rights reserved. +#pragma once +#include "precomp.h" +#include "wifiHAL.h" +#include "wifirequest.h" + +// Generic execution context passed between steps and parse/handle +struct TransitionContext +{ + WDFDEVICE Device; + PWIFI_IHV_DEVICE_CONTEXT DevCtx; + WIFIREQUEST WifiRequest; + PWDI_MESSAGE_HEADER Header; + void* RawBuffer; // from WifiRequestGetInOutBuffer in EvtWifiDeviceSendCommand + UINT InLen; + UINT OutLen; +}; + +// -------- Runtime dispatcher (decl) -------- +NTSTATUS RunTransitionByMessage(TransitionContext& ctx, UINT16 messageId);
\ No newline at end of file diff --git a/network/wlan/wificx/km/wificxsampleclientkm.inf b/network/wlan/wificx/km/wificxsampleclientkm.inf new file mode 100644 index 00000000..1968ff32 --- /dev/null +++ b/network/wlan/wificx/km/wificxsampleclientkm.inf @@ -0,0 +1,96 @@ +;Copyright (c) Microsoft Corporation. All rights reserved. +; wificxsampleclientkm.inf +; + +[Version] +Signature = "$WINDOWS NT$" +Class = NET +ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %ManufacturerName% +CatalogFile = wificxsampleclientkm.cat +DriverVer = ; TODO: set DriverVer in stampinf property pages +PnpLockdown = 1 + +[DestinationDirs] +DefaultDestDir = 13 + +[SourceDisksNames] +1 = %DiskName%,,,"" + +[SourceDisksFiles] +wificxsampleclientkm.sys = 1,, + +;***************************************** +; Install Section +;***************************************** + +[Manufacturer] +%ManufacturerName% = Standard,NT$ARCH$.10.0...16299 ; %13% support introduced in build 16299 + +[Standard.NT$ARCH$.10.0...16299] +%wificxsampleclientkm.DeviceDesc% = wificxsampleclientkm_Device.ndi, Root\wificxsampleclientkm + +; +; Normal device - Networking Section +; +[wificxsampleclientkm_Device.ndi.NT] +CopyFiles = File_Copy +Characteristics = 0x84 ; NCF_HAS_UI, NCF_PHYSICAL +BusType = 0 ; Internal +AddReg = wificxsampleclientkm.reg, netvadapter.params +*IfType = 71 ; IF_TYPE_IEEE80211 +*MediaType = 16 ; NdisMediumNative802_11 +*PhysicalMediaType = 9 ; NdisPhysicalMediumNative802_11 + +[File_Copy] +wificxsampleclientkm.sys + +;-------------- Service installation +[wificxsampleclientkm_Device.ndi.NT.Services] +AddService = wificxsampleclientkm,%SPSVCINST_ASSOCSERVICE%, wificxsampleclientkm_Service_Inst + +; -------------- wificxsampleclientkm driver install sections +[wificxsampleclientkm_Service_Inst] +DisplayName = %wificxsampleclientkm.SVCDESC% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %13%\wificxsampleclientkm.sys + +[wificxsampleclientkm_Device.ndi.NT.Wdf] +KmdfService = wificxsampleclientkm, wificxsampleclientkm_wdfsect + +[wificxsampleclientkm_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + + +[wificxsampleclientkm.reg] +HKR, Ndi, Service, 0, "wificxsampleclientkm" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "wlan,ethernet" +; standard INF keywords for NetAdapter drivers +; using AddReg directive so they will work when this INF being Includes/Needs + +HKR, NetworkInterface, *IfConnectorPresent, 0x00010001, 1 +HKR, NetworkInterface, *ConnectionType, 0x00010001, 1 +HKR, NetworkInterface, *DirectionType, 0x00010001, 0 +HKR, NetworkInterface, *AccessType, 0x00010001, 2 +HKR, NetworkInterface, *HardwareLoopback, 0x00010001, 0 +HKR, , NumberOfNetworkInterfaces, 0x00010001, 11 + +[Strings] +SPSVCINST_ASSOCSERVICE = 0x00000002 +ManufacturerName = "WDK Sample" +DiskName = "Wificxsampleclientkm Installation Disk" +wificxsampleclientkm.DeviceDesc = "[KMDF]Wificx Sample Client Device" +wificxsampleclientkm.SVCDESC = "Wificxsampleclientkm Service" + +[netvadapter.params] +; MACLastByte + HKR, Ndi\params\MACLastByte, ParamDesc, 0, "MACLastByte" + HKR, Ndi\params\MACLastByte, default, 0, "1" + HKR, Ndi\params\MACLastByte, type, 0, "int" + HKR, Ndi\params\MACLastByte, min, 0, "1" + HKR, Ndi\params\MACLastByte, max, 0, "254" + HKR, Ndi\params\MACLastByte, step, 0, "1" + HKR, Ndi\params\MACLastByte, Optional, 0, "0"
\ No newline at end of file diff --git a/network/wlan/wificx/km/wificxsampleclientkm.vcxproj b/network/wlan/wificx/km/wificxsampleclientkm.vcxproj new file mode 100644 index 00000000..08f69e0f --- /dev/null +++ b/network/wlan/wificx/km/wificxsampleclientkm.vcxproj @@ -0,0 +1,246 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <PropertyGroup Label="Globals"> + <ProjectGuid>{272D3E7B-C7BA-66D1-E05D-B9723A6F0777}</ProjectGuid> + <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>wificxsampleclientkm</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>6</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED> + </NETADAPTER_MINIMUM_VERSION_REQUIRED> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_VERSION_MINOR> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_VERSION_MINOR> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_VERSION_MINOR> + <SupportsPackaging>true</SupportsPackaging> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + <DriverType>KMDF</DriverType> + <DriverTargetPlatform>Windows Driver</DriverTargetPlatform> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <KMDF_VERSION_MINOR>33</KMDF_VERSION_MINOR> + <KMDF_MINIMUM_VERSION_REQUIRED>33</KMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <NETADAPTER_MINIMUM_VERSION_REQUIRED>4</NETADAPTER_MINIMUM_VERSION_REQUIRED> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_VERSION_MINOR> + <SupportsPackaging>true</SupportsPackaging> + </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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> + <RunCodeAnalysis>false</RunCodeAnalysis> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <WppEnabled>true</WppEnabled> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(DDK_INC_PATH)wlan\2.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(DDK_INC_PATH)wlan\2.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(DDK_INC_PATH)wlan\2.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(DDK_INC_PATH)wlan\2.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <WppEnabled>true</WppEnabled> + <WppRecorderEnabled>true</WppRecorderEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>$(DDK_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + <Inf> + <TimeStamp>1.0</TimeStamp> + </Inf> + </ItemDefinitionGroup> + <ItemGroup> + <Inf Include="wificxsampleclientkm.inf" /> + </ItemGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\adapter.cpp" /> + <ClCompile Include="..\drivercode\wifirequest.cpp" /> + <ClCompile Include="..\drivercode\device.cpp" /> + <ClCompile Include="..\drivercode\driver.cpp" /> + <ClCompile Include="..\drivercode\memorymanagement.cpp" /> + <ClCompile Include="..\drivercode\wifihal.cpp" /> + <ClCompile Include="..\drivercode\wifitransition.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\adapter.h" /> + <ClInclude Include="..\drivercode\device.h" /> + <ClInclude Include="..\drivercode\driver.h" /> + <ClInclude Include="..\drivercode\sharedtypes.h" /> + <ClInclude Include="..\drivercode\umkmfusion.h" /> + <ClInclude Include="..\drivercode\wifihaltestdata.h" /> + <ClInclude Include="..\drivercode\wifirequest.h" /> + <ClInclude Include="..\drivercode\precomp.h" /> + <ClInclude Include="..\drivercode\trace.h" /> + <ClInclude Include="..\drivercode\wifihal.h" /> + <ClInclude Include="..\drivercode\wifitransition.h" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\netadaptercx\netvadapterlibrary\wifi_km\netvadapterlibrarykm.vcxproj"> + <Project>{e2a65efd-25cc-4af0-b180-0cd56ee277a9}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/wlan/wificx/km/wificxsampleclientkm.vcxproj.filters b/network/wlan/wificx/km/wificxsampleclientkm.vcxproj.filters new file mode 100644 index 00000000..2930b24d --- /dev/null +++ b/network/wlan/wificx/km/wificxsampleclientkm.vcxproj.filters @@ -0,0 +1,84 @@ +<?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="wificxsampleclientkm.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\adapter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifirequest.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\memorymanagement.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifihal.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifitransition.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\adapter.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\device.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\driver.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\sharedtypes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\umkmfusion.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifihaltestdata.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifirequest.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\precomp.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\trace.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifihal.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifitransition.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/wlan/wificx/um/wificxsampleclientum.inf b/network/wlan/wificx/um/wificxsampleclientum.inf new file mode 100644 index 00000000..98633234 --- /dev/null +++ b/network/wlan/wificx/um/wificxsampleclientum.inf @@ -0,0 +1,107 @@ +;Copyright (c) Microsoft Corporation. All rights reserved. +; wificxsampleclientum.inf +; + +[Version] +Signature = $Windows NT$ +Class = NET +ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %ManufacturerName% +CatalogFile = wificxsampleclientum.cat +DriverVer = ; TODO: set DriverVer in stampinf property pages +PnpLockdown = 1 + +[Manufacturer] +; This driver package is only installable on Win11+ +%ManufacturerName% = Standard,NT$ARCH$.10.0...22000 ; wudfrd.inf introduced in build 22000 + +[Standard.NT$ARCH$.10.0...22000] +%DeviceName% = Wificxsampleclientum_Device.ndi, Root\wificxsampleclientum + +; +; Normal device - Networking Section +; +[Wificxsampleclientum_Device.ndi] +Include=wudfrd.inf, netcxrd.inf +Needs=WUDFRD.NT, netcxrd_Filter.NT + +Characteristics = 0x1 ; NCF_VIRTUAL +*IfType = 71 ; IF_TYPE_IEEE80211 +*MediaType = 16 ; NdisMediumNative802_11 +*PhysicalMediaType = 9 ; NdisPhysicalMediumNative802_11 +BusType = 15 ; PnpBus +NumberOfNetworkInterfaces = 5 +AddReg = Wificxsampleclientum.reg, netvadapter.params +CopyFiles = Wificxsampleclientum.Copy + +[Wificxsampleclientum_Device.ndi.Hw] +Include=wudfrd.inf, netcxrd.inf +Needs=WUDFRD.NT.HW, netcxrd_Filter.NT.HW + +[Wificxsampleclientum_Device.ndi.Filters] +Include=netcxrd.inf +Needs=netcxrd_Filter.NT.Filters + +[Wificxsampleclientum_Device.ndi.Services] +Include=wudfrd.inf, netcxrd.inf +Needs=WUDFRD.NT.Services, netcxrd_Filter.NT.Services + +[Wificxsampleclientum_Device.ndi.Wdf] +UmdfService = "Wificxsampleclientum", wdf +UmdfServiceOrder=wificxsampleclientum +UmdfHostProcessSharing=ProcessSharingDisabled +UmdfKernelModeClientPolicy=AllowKernelModeClients +UmdfDirectHardwareAccess=AllowDirectHardwareAccessAndDma +UmdfRegisterAccessMode=RegisterAccessUsingUserModeMapping +UmdfFsContextUsePolicy=CanUseFsContext2 + +[wdf] +UmdfLibraryVersion = 2.33.0 +UmdfExtensions = NetAdapterCx0202,WifiCx0102 +ServiceBinary=%13%\wificxtestclient.dll +; +; Common - Generic INF sections +; +[Wificxsampleclientum.reg] +HKR, , BusNumber, 0, "0" +HKR, Ndi, Service, 0, "Wificxsampleclientum" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "wlan,ethernet" + +; standard INF keywords for NetAdapter drivers +; using AddReg directive so they will work when this INF being Includes/Needs +HKR, NetworkInterface, *IfConnectorPresent, 0x00010001, 1 +HKR, NetworkInterface, *ConnectionType, 0x00010001, 1 +HKR, NetworkInterface, *DirectionType, 0x00010001, 0 +HKR, NetworkInterface, *AccessType, 0x00010001, 2 +HKR, NetworkInterface, *HardwareLoopback, 0x00010001, 0 +HKR, , NumberOfNetworkInterfaces, 0x00010001, 11 + +[Wificxsampleclientum.Copy] +wificxsampleclientum.dll + +[SourceDisksNames] +1 = %DiskName%,,,"" + +[DestinationDirs] +Wificxsampleclientum.Copy = 13 + +[SourceDisksFiles] +wificxsampleclientum.dll = 1 + +; =================== Generic ================================== + +[Strings] +ManufacturerName = "WDK Sample" +DiskName = "wificxsampleclientum Installation Disk" +DeviceName = "[UMDF] Wificx Sample Client Device" + +[netvadapter.params] +; MACLastByte + HKR, Ndi\params\MACLastByte, ParamDesc, 0, "MACLastByte" + HKR, Ndi\params\MACLastByte, default, 0, "1" + HKR, Ndi\params\MACLastByte, type, 0, "int" + HKR, Ndi\params\MACLastByte, min, 0, "1" + HKR, Ndi\params\MACLastByte, max, 0, "254" + HKR, Ndi\params\MACLastByte, step, 0, "1" + HKR, Ndi\params\MACLastByte, Optional, 0, "0"
\ No newline at end of file diff --git a/network/wlan/wificx/um/wificxsampleclientum.vcxproj b/network/wlan/wificx/um/wificxsampleclientum.vcxproj new file mode 100644 index 00000000..5bb17f54 --- /dev/null +++ b/network/wlan/wificx/um/wificxsampleclientum.vcxproj @@ -0,0 +1,229 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</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> + <Inf Include="wificxsampleclientum.inf" /> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C804D7D0-80D8-1409-44DA-91EF3260D07F}</ProjectGuid> + <TemplateGuid>{2177f19c-eb4c-4687-9e7f-f9eec1f12cf1}</TemplateGuid> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion> + <Configuration>Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">x64</Platform> + <RootNamespace>wificxsampleclientum</RootNamespace> + </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|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|x64'" Label="Configuration"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>true</UseDebugLibraries> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <UMDF_VERSION_MINOR>35</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>35</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>6</NETADAPTER_VERSION_MINOR> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_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>35</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>35</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_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>35</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>35</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_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>35</UMDF_VERSION_MINOR> + <UMDF_MINIMUM_VERSION_REQUIRED>35</UMDF_MINIMUM_VERSION_REQUIRED> + <NetAdapterDriver>true</NetAdapterDriver> + <NETADAPTER_VERSION_MAJOR>2</NETADAPTER_VERSION_MAJOR> + <NETADAPTER_VERSION_MINOR>5</NETADAPTER_VERSION_MINOR> + <WifiDriver>true</WifiDriver> + <WIFI_VERSION_MAJOR>1</WIFI_VERSION_MAJOR> + <WIFI_VERSION_MINOR>2</WIFI_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 /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor> + <EnableInf2cat>false</EnableInf2cat> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(WDK_UM_INC_PATH)wlan\2.0;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIFICX_TEMPORARY_REMOVED_FOR_USERMODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Link> + <AdditionalDependencies>$(WDK_UM_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(WDK_UM_INC_PATH)wlan\2.0;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIFICX_TEMPORARY_REMOVED_FOR_USERMODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Link> + <AdditionalDependencies>$(WDK_UM_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(WDK_UM_INC_PATH)wlan\2.0;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIFICX_TEMPORARY_REMOVED_FOR_USERMODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Link> + <AdditionalDependencies>$(WDK_UM_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <DriverSign> + <FileDigestAlgorithm>sha256</FileDigestAlgorithm> + </DriverSign> + <ClCompile> + <AdditionalIncludeDirectories>..\..\..\netadaptercx\netvadapterlibrary\Interface;$(WDK_UM_INC_PATH)wlan\2.0;$(KIT_SHARED_INC_PATH_WDK);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIFICX_TEMPORARY_REMOVED_FOR_USERMODE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <WppEnabled>true</WppEnabled> + <WppScanConfigurationData>..\drivercode\trace.h</WppScanConfigurationData> + <WppMinimalRebuildFromTracking>false</WppMinimalRebuildFromTracking> + <PreprocessToFile>false</PreprocessToFile> + <WppRecorderEnabled>true</WppRecorderEnabled> + </ClCompile> + <Link> + <AdditionalDependencies>$(WDK_UM_LIB_PATH)wlan\2.0\WificxTLVGenParse.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <FilesToPackage Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\adapter.h" /> + <ClInclude Include="..\drivercode\device.h" /> + <ClInclude Include="..\drivercode\driver.h" /> + <ClInclude Include="..\drivercode\precomp.h" /> + <ClInclude Include="..\drivercode\sharedtypes.h" /> + <ClInclude Include="..\drivercode\wifihaltestdata.h" /> + <ClInclude Include="..\drivercode\trace.h" /> + <ClInclude Include="..\drivercode\wifihal.h" /> + <ClInclude Include="..\drivercode\wifirequest.h" /> + <ClInclude Include="..\drivercode\umkmfusion.h" /> + <ClInclude Include="..\drivercode\wifitransition.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\adapter.cpp" /> + <ClCompile Include="..\drivercode\device.cpp" /> + <ClCompile Include="..\drivercode\driver.cpp" /> + <ClCompile Include="..\drivercode\memorymanagement.cpp" /> + <ClCompile Include="..\drivercode\wifihal.cpp" /> + <ClCompile Include="..\drivercode\wifirequest.cpp" /> + <ClCompile Include="..\drivercode\wifitransition.cpp" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\netadaptercx\netvadapterlibrary\wifi_um\netvadapterlibraryum.vcxproj"> + <Project>{612f33ad-430c-4fe7-8000-35e15a5eb757}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/wlan/wificx/um/wificxsampleclientum.vcxproj.filters b/network/wlan/wificx/um/wificxsampleclientum.vcxproj.filters new file mode 100644 index 00000000..a10fb659 --- /dev/null +++ b/network/wlan/wificx/um/wificxsampleclientum.vcxproj.filters @@ -0,0 +1,84 @@ +<?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="wificxsampleclientum.inf"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\drivercode\adapter.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\device.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\driver.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\precomp.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\sharedtypes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifihaltestdata.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\trace.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifirequest.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\umkmfusion.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifihal.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\drivercode\wifitransition.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\drivercode\adapter.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\memorymanagement.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifirequest.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifihal.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\drivercode\wifitransition.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/wlan/wificx/video/ControlPath.mp4 b/network/wlan/wificx/video/ControlPath.mp4 Binary files differnew file mode 100644 index 00000000..15ec3d62 --- /dev/null +++ b/network/wlan/wificx/video/ControlPath.mp4 diff --git a/network/wlan/wificx/video/DataPath.mp4 b/network/wlan/wificx/video/DataPath.mp4 Binary files differnew file mode 100644 index 00000000..fda748e5 --- /dev/null +++ b/network/wlan/wificx/video/DataPath.mp4 diff --git a/network/wlan/wificx/wificxsampleclient.sln b/network/wlan/wificx/wificxsampleclient.sln new file mode 100644 index 00000000..c3bf1f22 --- /dev/null +++ b/network/wlan/wificx/wificxsampleclient.sln @@ -0,0 +1,92 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11903.348 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wificxsampleclientkm", "km\wificxsampleclientkm.vcxproj", "{272D3E7B-C7BA-66D1-E05D-B9723A6F0777}" + ProjectSection(ProjectDependencies) = postProject + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9} = {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wificxsampleclientum", "um\wificxsampleclientum.vcxproj", "{C804D7D0-80D8-1409-44DA-91EF3260D07F}" + ProjectSection(ProjectDependencies) = postProject + {612F33AD-430C-4FE7-8000-35E15A5EB757} = {612F33AD-430C-4FE7-8000-35E15A5EB757} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OemDeviceServiceApplication", "OEM\OemDeviceService.vcxproj", "{B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterlibrarykm", "..\..\netadaptercx\netvadapterlibrary\wifi_km\netvadapterlibrarykm.vcxproj", "{E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netvadapterlibraryum", "..\..\netadaptercx\netvadapterlibrary\wifi_um\netvadapterlibraryum.vcxproj", "{612F33AD-430C-4FE7-8000-35E15A5EB757}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|ARM64.Build.0 = Debug|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|x64.ActiveCfg = Debug|x64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|x64.Build.0 = Debug|x64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Debug|x64.Deploy.0 = Debug|x64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|ARM64.ActiveCfg = Release|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|ARM64.Build.0 = Release|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|ARM64.Deploy.0 = Release|ARM64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|x64.ActiveCfg = Release|x64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|x64.Build.0 = Release|x64 + {272D3E7B-C7BA-66D1-E05D-B9723A6F0777}.Release|x64.Deploy.0 = Release|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|ARM64.Build.0 = Debug|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|x64.ActiveCfg = Debug|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|x64.Build.0 = Debug|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Debug|x64.Deploy.0 = Debug|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|ARM64.ActiveCfg = Release|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|ARM64.Build.0 = Release|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|ARM64.Deploy.0 = Release|ARM64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|x64.ActiveCfg = Release|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|x64.Build.0 = Release|x64 + {C804D7D0-80D8-1409-44DA-91EF3260D07F}.Release|x64.Deploy.0 = Release|x64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Debug|ARM64.Build.0 = Debug|ARM64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Debug|x64.ActiveCfg = Debug|x64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Debug|x64.Build.0 = Debug|x64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Release|ARM64.ActiveCfg = Release|ARM64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Release|ARM64.Build.0 = Release|ARM64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Release|x64.ActiveCfg = Release|x64 + {B3C9A1E2-7F4D-4B2A-9C5E-1A2B3C4D5E6F}.Release|x64.Build.0 = Release|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|ARM64.Build.0 = Debug|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|x64.ActiveCfg = Debug|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|x64.Build.0 = Debug|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Debug|x64.Deploy.0 = Debug|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|ARM64.ActiveCfg = Release|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|ARM64.Build.0 = Release|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|ARM64.Deploy.0 = Release|ARM64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|x64.ActiveCfg = Release|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|x64.Build.0 = Release|x64 + {E2A65EFD-25CC-4AF0-B180-0CD56EE277A9}.Release|x64.Deploy.0 = Release|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|ARM64.Build.0 = Debug|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|x64.ActiveCfg = Debug|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|x64.Build.0 = Debug|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Debug|x64.Deploy.0 = Debug|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|ARM64.ActiveCfg = Release|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|ARM64.Build.0 = Release|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|ARM64.Deploy.0 = Release|ARM64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|x64.ActiveCfg = Release|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|x64.Build.0 = Release|x64 + {612F33AD-430C-4FE7-8000-35E15A5EB757}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {37680CDC-EACB-499B-BA11-7C376F53DB71} + EndGlobalSection +EndGlobal diff --git a/packages.config b/packages.config index 005aead0..d2a0bc5c 100644 --- a/packages.config +++ b/packages.config @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Microsoft.Windows.SDK.CPP" version="10.0.26100.6584" targetFramework="native" /> - <package id="Microsoft.Windows.SDK.CPP.x64" version="10.0.26100.6584" targetFramework="native" /> - <package id="Microsoft.Windows.SDK.CPP.arm64" version="10.0.26100.6584" targetFramework="native" /> - <package id="Microsoft.Windows.WDK.x64" version="10.0.26100.6584" targetFramework="native" /> - <package id="Microsoft.Windows.WDK.arm64" version="10.0.26100.6584" targetFramework="native" /> + <package id="Microsoft.Windows.SDK.CPP" version="10.0.28000.1839" targetFramework="native" /> + <package id="Microsoft.Windows.SDK.CPP.x64" version="10.0.28000.1839" targetFramework="native" /> + <package id="Microsoft.Windows.SDK.CPP.arm64" version="10.0.28000.1839" targetFramework="native" /> + <package id="Microsoft.Windows.WDK.x64" version="10.0.28000.1839" targetFramework="native" /> + <package id="Microsoft.Windows.WDK.arm64" version="10.0.28000.1839" targetFramework="native" /> </packages> diff --git a/setup/devcon/msg.mc b/setup/devcon/msg.mc index 110bb2f8..8ecb8fae 100644 --- a/setup/devcon/msg.mc +++ b/setup/devcon/msg.mc @@ -12,7 +12,7 @@ For more information, type: %1 help . MessageId=60001 SymbolicName=MSG_FAILURE Language=English -%1 failed. +%1: command %2 failed . MessageId=60002 SymbolicName=MSG_COMMAND_USAGE Language=English |
