mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
Compare commits
61 Commits
v1.17.306.
...
v1.18.367.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cbb3357dc | ||
|
|
efe14cd917 | ||
|
|
6942f17e36 | ||
|
|
ee83bbaa45 | ||
|
|
83b89dc860 | ||
|
|
fa43acce66 | ||
|
|
735ee2984f | ||
|
|
10825759c8 | ||
|
|
53673bda45 | ||
|
|
da4b8419f5 | ||
|
|
01b9ebd75e | ||
|
|
a9e7d6b38b | ||
|
|
7411c4fee3 | ||
|
|
816ebc524f | ||
|
|
4316457837 | ||
|
|
3102c94dfc | ||
|
|
442ae3b856 | ||
|
|
41cc4f8398 | ||
|
|
a33e223774 | ||
|
|
d24ab69f45 | ||
|
|
7d3027c7db | ||
|
|
a1b58be426 | ||
|
|
9fdbe34bac | ||
|
|
346548689d | ||
|
|
111ff8e170 | ||
|
|
c5ecfbdd03 | ||
|
|
df39fe6ed3 | ||
|
|
2b02e029c1 | ||
|
|
dce6de1a6f | ||
|
|
4ddf7639e3 | ||
|
|
b4980ceb82 | ||
|
|
23052bcb67 | ||
|
|
6ef839228d | ||
|
|
40aa12d889 | ||
|
|
b22bb6b665 | ||
|
|
8b8ba943b1 | ||
|
|
47a28733cd | ||
|
|
dc2feda23c | ||
|
|
4001a9990b | ||
|
|
5861ea36f3 | ||
|
|
f14ba5db9c | ||
|
|
92e6937633 | ||
|
|
2eb8a2e349 | ||
|
|
9f5247fd57 | ||
|
|
ad1373248d | ||
|
|
3fcdec87da | ||
|
|
8567ee21b4 | ||
|
|
a958721b44 | ||
|
|
16fb8a2bb1 | ||
|
|
97fd8fd9fa | ||
|
|
c3c4047cfa | ||
|
|
703842c753 | ||
|
|
5d39f31a13 | ||
|
|
a3c05a5aca | ||
|
|
0afae253b8 | ||
|
|
8f1ddc86db | ||
|
|
1a401ff65b | ||
|
|
27555457a7 | ||
|
|
9adbb268ed | ||
|
|
a8dc03a661 | ||
|
|
75c007b4c4 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,2 +0,0 @@
|
||||
patreon: nefarius
|
||||
custom: ["https://paypal.me/NefariusMaximus"]
|
||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Community support
|
||||
url: https://vigem.org/Community-Support/
|
||||
about: Use these resources for support.
|
||||
- name: 📖 Documentation
|
||||
url: https://vigem.org/projects/
|
||||
about: Extended documentation about the projects.
|
||||
- name: ❓ Other issue?
|
||||
url: https://forums.vigem.org/
|
||||
about: Search on the community forums.
|
||||
30
.github/ISSUE_TEMPLATE/use-this-for-problems-with-the-setup.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/use-this-for-problems-with-the-setup.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Setup issues
|
||||
about: Use this if you have problems with the setup
|
||||
|
||||
---
|
||||
|
||||
## README first
|
||||
|
||||
Before you report issues with the setup, make sure to check the following things **first**:
|
||||
|
||||
- Are you on anything older than Windows **10**? Windows XP/Vista/7/8/8.1 **are not supported** so don't report this as an issue, it is intentional.
|
||||
- [Have you chosen the right setup for your CPU architecture?](https://vigem.org/research/How-to-check-architecture/)
|
||||
- You **can not mix these**, make sure to download and run the correct setup.
|
||||
- **ARM/ARM64** is **not supported**. See above link to check for yourself.
|
||||
|
||||
## I verified all that and am still stuck
|
||||
|
||||
Please provide the following **log files** and attach them to the issue. Failing to do so will result in the issue being closed without any further comment.
|
||||
|
||||
### Setup log
|
||||
|
||||
Run the setup from the command line (either old-school `cmd` or PowerShell) with the following additional arguments: `/L*V .\install.log`
|
||||
|
||||
This will generate the log file `install.log` in the same directory the setup resides in. Attach it once the setup is "done" failing.
|
||||
|
||||
Last but not least look for `C:\Windows\INF\setupapi.dev.log` and attach it as well.
|
||||
|
||||
Optionally compress both files down if it gives you troubles uploading.
|
||||
|
||||
Your compliance is appreciated! 😘
|
||||
7
.github/ISSUE_TEMPLATE/you-need-support.md
vendored
7
.github/ISSUE_TEMPLATE/you-need-support.md
vendored
@@ -1,7 +0,0 @@
|
||||
---
|
||||
name: You need support
|
||||
about: This is the wrong place to ask for support
|
||||
|
||||
---
|
||||
|
||||
**Please don't abuse the issue tracker as a helpdesk!** We have a Discord server (linked in the README) where you can ask the lovely like-minded folks for assistance. Thank you for your compliance :smiley:
|
||||
25
.github/workflows/support.yml
vendored
Normal file
25
.github/workflows/support.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: 'Support Requests'
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled, unlabeled, reopened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/support-requests@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
support-label: 'support'
|
||||
issue-comment: >
|
||||
:wave: @{issue-author}, we use the issue tracker exclusively
|
||||
for bug reports and feature requests. However, this issue appears
|
||||
to be a support request. Please use our support channels
|
||||
to get help with the project.
|
||||
close-issue: true
|
||||
lock-issue: true
|
||||
issue-lock-reason: 'off-topic'
|
||||
30
README.md
30
README.md
@@ -37,19 +37,30 @@ A few examples of the most common use cases for `ViGEm` are:
|
||||
|
||||
## Supported Systems
|
||||
|
||||
The driver is built for Windows 7/8.1/10 (x86 and amd64).
|
||||
### Version 1.16 and below
|
||||
|
||||
The driver is built for Windows 7/8.1/10/Server 2016/Server 2019 (x86 and amd64).
|
||||
|
||||
### Version 1.17 and above
|
||||
|
||||
The driver is built for Windows 10/Server 2016/Server 2019 only (x86 and amd64).
|
||||
|
||||
## License
|
||||
|
||||
The `ViGEm` Bus Driver is licensed under the **BSD-3-Clause**, see [LICENSE](./LICENSE.md) for more information.
|
||||
The ViGEm Bus Driver is licensed under the **BSD-3-Clause**, see [LICENSE](./LICENSE.md) for more information.
|
||||
|
||||
## How to build
|
||||
|
||||
[Install Visual Studio 2019 and WDK for Windows 10, version 1903](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk#wdk-for-windows-10-version-1903).
|
||||
### Prerequisites
|
||||
|
||||
- [Step 1: Install Visual Studio 2019](https://docs.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads#step-1-install-visual-studio)
|
||||
- [Step 2: Install WDK for Windows 10, version 2004](https://docs.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads#step-2-install-the-wdk)
|
||||
- [Step 3: Clone the Driver Module Framework (DMF)](https://github.com/microsoft/DMF) into the same parent directory.
|
||||
- Build the `DmfK` project with Release and Debug configurations for all architectures (x64 and Win32).
|
||||
|
||||
You can build directly within Visual Studio.
|
||||
|
||||
Do bear in mind that you'll need to **sign** the driver to use it without [test mode](<https://technet.microsoft.com/en-us/ff553484(v=vs.96)>).
|
||||
Do bear in mind that you'll need to **sign** the driver to use it without [test mode](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/the-testsigning-boot-configuration-option#enable-or-disable-use-of-test-signed-code).
|
||||
|
||||
## Contribute
|
||||
|
||||
@@ -72,8 +83,8 @@ Pre-built production-signed binaries are provided by `Nefarius Software Solution
|
||||
Sponsors listed here have helped the project flourish by either financial support or by gifting licenses:
|
||||
|
||||
- [3dRudder](https://www.3drudder.com/)
|
||||
- [Parsec](https://parsecgaming.com/)
|
||||
- [Rainway, Inc](https://rainway.io/)
|
||||
- [Parsec](https://parsec.app/)
|
||||
- [Rainway, Inc](https://rainway.com/)
|
||||
- [JetBrains](https://www.jetbrains.com/resharper/)
|
||||
- [Advanced Installer](https://www.advancedinstaller.com/)
|
||||
- [ICAROS](https://www.icaros.com/)
|
||||
@@ -85,18 +96,19 @@ A brief listing of projects/companies/vendors known to build upon the powers of
|
||||
This list is non-exhaustive, if you'd like to see your project included, contact us!
|
||||
|
||||
- [3dRudder](https://www.3drudder.com/)
|
||||
- [Parsec](https://parsecgaming.com/)
|
||||
- [Parsec](https://parsec.app/)
|
||||
- [GloSC](https://github.com/Alia5/GloSC)
|
||||
- [UCR](https://github.com/Snoothy/UCR)
|
||||
- [InputMapper](https://inputmapper.com/)
|
||||
- [Oculus VR, LLC.](https://www.oculus.com/)
|
||||
- [Rainway, Inc](https://rainway.io/)
|
||||
- [Rainway, Inc](https://rainway.com/)
|
||||
- [WiimoteHook](https://forum.cemu.info/showthread.php/140-WiimoteHook-Nintendo-Wii-Remote-with-Motion-Rumble-and-Nunchuk-support)
|
||||
- [XJoy](https://github.com/sam0x17/XJoy)
|
||||
- [HP](https://www8.hp.com/us/en/campaigns/gamingpcs/overview.html)
|
||||
- [HP](https://www8.hp.com/us/en/gaming/omen.html)
|
||||
- [DS4Windows](https://ryochan7.github.io/ds4windows-site/)
|
||||
- [XOutput](https://github.com/csutorasa/XOutput)
|
||||
- [RdpGamepad](https://github.com/microsoft/RdpGamepad)
|
||||
- [Touchmote](https://github.com/Ryochan7/Touchmote/tree/ryochan7)
|
||||
- [Mi-ViGEm](https://github.com/grayver/mi-vigem)
|
||||
- [BetterJoy](https://github.com/Davidobot/BetterJoy)
|
||||
- [Regame - Cloud Gaming Engine](https://github.com/ksyun-kenc/liuguang)
|
||||
|
||||
14
ViGEmBus.sln
14
ViGEmBus.sln
@@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup", "Setup", "{D138F6D3
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ViGEmBusSetup", "setup\ViGEmBusSetup.wixproj", "{C722B85E-FC7D-475F-A518-C8E13ECDB201}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug_DLL|x64 = Debug_DLL|x64
|
||||
@@ -114,6 +116,18 @@ Global
|
||||
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x64.Build.0 = Release|x64
|
||||
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x86.ActiveCfg = Release|x86
|
||||
{C722B85E-FC7D-475F-A518-C8E13ECDB201}.Release|x86.Build.0 = Release|x86
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_DLL|x64.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_DLL|x86.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_LIB|x64.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug_LIB|x86.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_DLL|x64.ActiveCfg = Release|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_DLL|x86.ActiveCfg = Release|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_LIB|x64.ActiveCfg = Release|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release_LIB|x86.ActiveCfg = Release|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C2BA387E-D491-4FB7-8BEE-99D77E8949E7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -15,5 +15,4 @@
|
||||
LICENSE
|
||||
bin\x64\ViGEmBus.pdb
|
||||
bin\x64\ViGEmBus\ViGEmBus.inf
|
||||
bin\x64\ViGEmBus\ViGEmBus.sys
|
||||
bin\x64\ViGEmBus\WdfCoinstaller01009.dll
|
||||
bin\x64\ViGEmBus\ViGEmBus.sys
|
||||
@@ -15,5 +15,4 @@
|
||||
LICENSE
|
||||
bin\x86\ViGEmBus.pdb
|
||||
bin\x86\ViGEmBus\ViGEmBus.inf
|
||||
bin\x86\ViGEmBus\ViGEmBus.sys
|
||||
bin\x86\ViGEmBus\WdfCoinstaller01009.dll
|
||||
bin\x86\ViGEmBus\ViGEmBus.sys
|
||||
19
appveyor.yml
19
appveyor.yml
@@ -1,24 +1,35 @@
|
||||
version: 1.17.{build}.0
|
||||
version: 1.18.{build}.0
|
||||
image: Visual Studio 2019
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/*.md'
|
||||
cache:
|
||||
- C:\projects\DMF
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
configuration:
|
||||
- Release
|
||||
install:
|
||||
- ps: iwr "https://download.microsoft.com/download/c/f/8/cf80b955-d578-4635-825c-2801911f9d79/wdk/wdksetup.exe" -OutFile wdksetup.exe
|
||||
- cmd: .\wdksetup.exe /features + /q /norestart
|
||||
- cmd: git submodule -q update --init
|
||||
- cmd: git clone -q https://github.com/microsoft/DMF.git C:\projects\DMF 2> nul || set ERRORLEVEL=0
|
||||
- cmd: |
|
||||
cd "C:\projects\DMF"
|
||||
git pull > NUL
|
||||
cd %appveyor_build_folder%
|
||||
before_build:
|
||||
- ps: Invoke-WebRequest "https://github.com/nefarius/vpatch/releases/latest/download/vpatch.exe" -OutFile vpatch.exe
|
||||
- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\ViGEmBus.vcxproj" --vcxproj.inf-time-stamp
|
||||
- cmd: vpatch.exe --stamp-version "%APPVEYOR_BUILD_VERSION%" --target-file ".\sys\ViGEmBus.rc" --resource.file-version --resource.product-version
|
||||
build:
|
||||
project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln
|
||||
build_script:
|
||||
- cmd: .\build.cmd
|
||||
after_build:
|
||||
- cmd: makecab.exe /f ViGEmBus_%PLATFORM%.ddf
|
||||
artifacts:
|
||||
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.inf'
|
||||
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.sys'
|
||||
- path: 'bin**\$(APPVEYOR_PROJECT_NAME)\*.dll'
|
||||
- path: 'bin**\*.pdb'
|
||||
- path: 'disk1\*.cab'
|
||||
- path: 'bin**\*.msi'
|
||||
|
||||
7
build.cmd
Executable file
7
build.cmd
Executable file
@@ -0,0 +1,7 @@
|
||||
:; set -eo pipefail
|
||||
:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
|
||||
:; ${SCRIPT_DIR}/build.sh "$@"
|
||||
:; exit $?
|
||||
|
||||
@ECHO OFF
|
||||
powershell -ExecutionPolicy ByPass -NoProfile %0\..\build.ps1 %*
|
||||
69
build.ps1
Normal file
69
build.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||
[string[]]$BuildArguments
|
||||
)
|
||||
|
||||
Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
|
||||
|
||||
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
$BuildProjectFile = "$PSScriptRoot\build\_build.csproj"
|
||||
$TempDirectory = "$PSScriptRoot\\.tmp"
|
||||
|
||||
$DotNetGlobalFile = "$PSScriptRoot\\global.json"
|
||||
$DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
|
||||
$DotNetChannel = "Current"
|
||||
|
||||
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
|
||||
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
|
||||
$env:DOTNET_MULTILEVEL_LOOKUP = 0
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function ExecSafe([scriptblock] $cmd) {
|
||||
& $cmd
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
}
|
||||
|
||||
# If dotnet CLI is installed globally and it matches requested version, use for execution
|
||||
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
|
||||
$(dotnet --version) -and $LASTEXITCODE -eq 0) {
|
||||
$env:DOTNET_EXE = (Get-Command "dotnet").Path
|
||||
}
|
||||
else {
|
||||
# Download install script
|
||||
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
|
||||
New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
|
||||
|
||||
# If global.json exists, load expected version
|
||||
if (Test-Path $DotNetGlobalFile) {
|
||||
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
|
||||
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
|
||||
$DotNetVersion = $DotNetGlobal.sdk.version
|
||||
}
|
||||
}
|
||||
|
||||
# Install by channel or version
|
||||
$DotNetDirectory = "$TempDirectory\dotnet-win"
|
||||
if (!(Test-Path variable:DotNetVersion)) {
|
||||
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
|
||||
} else {
|
||||
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
|
||||
}
|
||||
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
|
||||
}
|
||||
|
||||
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
|
||||
|
||||
ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
|
||||
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
|
||||
62
build.sh
Executable file
62
build.sh
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
bash --version 2>&1 | head -n 1
|
||||
|
||||
set -eo pipefail
|
||||
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
|
||||
|
||||
###########################################################################
|
||||
# CONFIGURATION
|
||||
###########################################################################
|
||||
|
||||
BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj"
|
||||
TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
|
||||
|
||||
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
|
||||
DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
|
||||
DOTNET_CHANNEL="Current"
|
||||
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
export DOTNET_MULTILEVEL_LOOKUP=0
|
||||
|
||||
###########################################################################
|
||||
# EXECUTION
|
||||
###########################################################################
|
||||
|
||||
function FirstJsonValue {
|
||||
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
|
||||
}
|
||||
|
||||
# If dotnet CLI is installed globally and it matches requested version, use for execution
|
||||
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
|
||||
export DOTNET_EXE="$(command -v dotnet)"
|
||||
else
|
||||
# Download install script
|
||||
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
|
||||
mkdir -p "$TEMP_DIRECTORY"
|
||||
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
|
||||
chmod +x "$DOTNET_INSTALL_FILE"
|
||||
|
||||
# If global.json exists, load expected version
|
||||
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
|
||||
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
|
||||
if [[ "$DOTNET_VERSION" == "" ]]; then
|
||||
unset DOTNET_VERSION
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install by channel or version
|
||||
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
|
||||
if [[ -z ${DOTNET_VERSION+x} ]]; then
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
|
||||
else
|
||||
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
|
||||
fi
|
||||
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
|
||||
fi
|
||||
|
||||
echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
|
||||
|
||||
"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
|
||||
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
|
||||
11
build/.editorconfig
Normal file
11
build/.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
[*.cs]
|
||||
dotnet_style_qualification_for_field = false:warning
|
||||
dotnet_style_qualification_for_property = false:warning
|
||||
dotnet_style_qualification_for_method = false:warning
|
||||
dotnet_style_qualification_for_event = false:warning
|
||||
dotnet_style_require_accessibility_modifiers = never:warning
|
||||
|
||||
csharp_style_expression_bodied_methods = true:silent
|
||||
csharp_style_expression_bodied_properties = true:warning
|
||||
csharp_style_expression_bodied_indexers = true:warning
|
||||
csharp_style_expression_bodied_accessors = true:warning
|
||||
79
build/Build.cs
Normal file
79
build/Build.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Nuke.Common;
|
||||
using Nuke.Common.CI;
|
||||
using Nuke.Common.CI.AppVeyor;
|
||||
using Nuke.Common.Execution;
|
||||
using Nuke.Common.Git;
|
||||
using Nuke.Common.IO;
|
||||
using Nuke.Common.ProjectModel;
|
||||
using Nuke.Common.Tooling;
|
||||
using Nuke.Common.Tools.MSBuild;
|
||||
using Nuke.Common.Utilities.Collections;
|
||||
using static Nuke.Common.EnvironmentInfo;
|
||||
using static Nuke.Common.IO.FileSystemTasks;
|
||||
using static Nuke.Common.IO.PathConstruction;
|
||||
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
|
||||
|
||||
[CheckBuildProjectConfigurations]
|
||||
class Build : NukeBuild
|
||||
{
|
||||
/// Support plugins are available for:
|
||||
/// - JetBrains ReSharper https://nuke.build/resharper
|
||||
/// - JetBrains Rider https://nuke.build/rider
|
||||
/// - Microsoft VisualStudio https://nuke.build/visualstudio
|
||||
/// - Microsoft VSCode https://nuke.build/vscode
|
||||
|
||||
public static int Main () => Execute<Build>(x => x.Compile);
|
||||
|
||||
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
|
||||
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
|
||||
|
||||
[Solution] readonly Solution Solution;
|
||||
[GitRepository] readonly GitRepository GitRepository;
|
||||
|
||||
AbsolutePath DmfSolution => RootDirectory / "../DMF/Dmf.sln";
|
||||
|
||||
Target Restore => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
MSBuild(s => s
|
||||
.SetTargetPath(Solution)
|
||||
.SetTargets("Restore"));
|
||||
});
|
||||
|
||||
Target BuildDmf => _ => _
|
||||
.Executes(() =>
|
||||
{
|
||||
if (IsLocalBuild)
|
||||
return;
|
||||
|
||||
Console.WriteLine($"DMF solution path: {DmfSolution}");
|
||||
|
||||
var platform = MSBuildTargetPlatform.x64;
|
||||
|
||||
if (AppVeyor.Instance.Platform != null && AppVeyor.Instance.Platform.Equals("x86"))
|
||||
platform = MSBuildTargetPlatform.Win32;
|
||||
|
||||
MSBuild(s => s
|
||||
.SetTargetPath(DmfSolution)
|
||||
.SetTargets("Build")
|
||||
.SetConfiguration(Configuration)
|
||||
.SetTargetPlatform(platform)
|
||||
.SetMaxCpuCount(Environment.ProcessorCount)
|
||||
.SetNodeReuse(IsLocalBuild));
|
||||
});
|
||||
|
||||
Target Compile => _ => _
|
||||
.DependsOn(BuildDmf)
|
||||
.Executes(() =>
|
||||
{
|
||||
MSBuild(s => s
|
||||
.SetTargetPath(Solution)
|
||||
.SetTargets("Rebuild")
|
||||
.SetConfiguration(Configuration)
|
||||
.SetMaxCpuCount(Environment.ProcessorCount)
|
||||
.SetNodeReuse(IsLocalBuild));
|
||||
});
|
||||
|
||||
}
|
||||
16
build/Configuration.cs
Normal file
16
build/Configuration.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Nuke.Common.Tooling;
|
||||
|
||||
[TypeConverter(typeof(TypeConverter<Configuration>))]
|
||||
public class Configuration : Enumeration
|
||||
{
|
||||
public static Configuration Debug = new Configuration { Value = nameof(Debug) };
|
||||
public static Configuration Release = new Configuration { Value = nameof(Release) };
|
||||
|
||||
public static implicit operator string(Configuration configuration)
|
||||
{
|
||||
return configuration.Value;
|
||||
}
|
||||
}
|
||||
16
build/_build.csproj
Normal file
16
build/_build.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace></RootNamespace>
|
||||
<NoWarn>CS0649;CS0169</NoWarn>
|
||||
<NukeRootDirectory>..</NukeRootDirectory>
|
||||
<NukeScriptDirectory>..</NukeScriptDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nuke.Common" Version="6.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
27
build/_build.csproj.DotSettings
Normal file
27
build/_build.csproj.DotSettings
Normal file
@@ -0,0 +1,27 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=HeapView_002EDelegateAllocation/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=VariableHidesOuterVariable/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBeMadeStatic_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Implicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">0</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ATTRIBUTE_LENGTH_FOR_SAME_LINE/@EntryValue">120</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
3
drivers/README.md
Normal file
3
drivers/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Drivers directory
|
||||
|
||||
Place the attestation signed driver files into the corresponding sub-directories and locally build the setup and sign it afterwards for production release.
|
||||
Binary file not shown.
Binary file not shown.
@@ -212,7 +212,7 @@ typedef struct _DS4_TOUCH
|
||||
BYTE bTouchData1[3]; // Two 12 bits values (for X and Y)
|
||||
// middle byte holds last 4 bits of X and the starting 4 bits of Y
|
||||
BYTE bIsUpTrackingNum2; // second touch data immediately follows data of first touch
|
||||
BYTE bTouchData2[3]; // resolution is 1920x943
|
||||
BYTE bTouchData2[3]; // resolution is 1920x942
|
||||
} DS4_TOUCH, * PDS4_TOUCH;
|
||||
|
||||
//
|
||||
|
||||
@@ -67,7 +67,5 @@ typedef struct _VIGEM_TARGET_T
|
||||
FARPROC Notification;
|
||||
LPVOID NotificationUserData;
|
||||
|
||||
bool closingNotificationThreads;
|
||||
HANDLE cancelNotificationThreadEvent;
|
||||
std::unique_ptr<std::vector<std::thread>> notificationThreadList;
|
||||
} VIGEM_TARGET;
|
||||
|
||||
@@ -74,76 +74,6 @@ LONG WINAPI vigem_internal_exception_handler(struct _EXCEPTION_POINTERS* apExcep
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// DeviceIOControl request notification handler classes for X360 and DS4 controller types.
|
||||
// vigem_target_XXX_register_notification functions use x360 or DS4 derived class instances in a notification thread handlers.
|
||||
//
|
||||
class NotificationRequestPayload
|
||||
{
|
||||
public:
|
||||
LPVOID lpPayloadBuffer;
|
||||
DWORD payloadBufferSize;
|
||||
DWORD ioControlCode;
|
||||
|
||||
public:
|
||||
NotificationRequestPayload(DWORD _bufferSize, DWORD _ioControlCode)
|
||||
{
|
||||
lpPayloadBuffer = malloc(_bufferSize);
|
||||
payloadBufferSize = _bufferSize;
|
||||
ioControlCode = _ioControlCode;
|
||||
}
|
||||
|
||||
virtual ~NotificationRequestPayload()
|
||||
{
|
||||
free(lpPayloadBuffer);
|
||||
}
|
||||
|
||||
virtual void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) = 0;
|
||||
};
|
||||
|
||||
class NotificationRequestPayloadX360 : public NotificationRequestPayload
|
||||
{
|
||||
public:
|
||||
NotificationRequestPayloadX360(ULONG _serialNo) : NotificationRequestPayload(sizeof(XUSB_REQUEST_NOTIFICATION), IOCTL_XUSB_REQUEST_NOTIFICATION)
|
||||
{
|
||||
// Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function
|
||||
XUSB_REQUEST_NOTIFICATION_INIT((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo);
|
||||
}
|
||||
|
||||
void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override
|
||||
{
|
||||
if(target->Notification != nullptr)
|
||||
PFN_VIGEM_X360_NOTIFICATION(target->Notification)(client, target,
|
||||
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LargeMotor,
|
||||
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->SmallMotor,
|
||||
((PXUSB_REQUEST_NOTIFICATION)lpPayloadBuffer)->LedNumber,
|
||||
target->NotificationUserData
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class NotificationRequestPayloadDS4 : public NotificationRequestPayload
|
||||
{
|
||||
public:
|
||||
NotificationRequestPayloadDS4(ULONG _serialNo) : NotificationRequestPayload(sizeof(DS4_REQUEST_NOTIFICATION), IOCTL_DS4_REQUEST_NOTIFICATION)
|
||||
{
|
||||
// Let base class to allocate required buffer size, but initialize it here with a correct type of initialization function
|
||||
DS4_REQUEST_NOTIFICATION_INIT((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer, _serialNo);
|
||||
}
|
||||
|
||||
void ProcessNotificationRequest(PVIGEM_CLIENT client, PVIGEM_TARGET target) override
|
||||
{
|
||||
if (target->Notification != nullptr)
|
||||
PFN_VIGEM_DS4_NOTIFICATION(target->Notification)(client, target,
|
||||
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LargeMotor,
|
||||
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.SmallMotor,
|
||||
((PDS4_REQUEST_NOTIFICATION)lpPayloadBuffer)->Report.LightbarColor,
|
||||
target->NotificationUserData
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Initializes a virtual gamepad object.
|
||||
//
|
||||
@@ -161,7 +91,6 @@ PVIGEM_TARGET FORCEINLINE VIGEM_TARGET_ALLOC_INIT(
|
||||
target->Size = sizeof(VIGEM_TARGET);
|
||||
target->State = VIGEM_TARGET_INITIALIZED;
|
||||
target->Type = Type;
|
||||
target->notificationThreadList = nullptr;
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -616,117 +545,6 @@ VIGEM_ERROR vigem_target_remove(PVIGEM_CLIENT vigem, PVIGEM_TARGET target)
|
||||
return VIGEM_ERROR_REMOVAL_FAILED;
|
||||
}
|
||||
|
||||
// Num of items in Notification DeviceIOControl queue (at any time there should be at least one extra call waiting for the new events or there is danger that notification events are lost).
|
||||
// The size of this queue is based on "scientific" experimentals and estimations (few games seem to sometimes flood the FFB driver interface).
|
||||
#define NOTIFICATION_OVERLAPPED_QUEUE_SIZE 6
|
||||
|
||||
void vigem_notification_thread_worker(
|
||||
PVIGEM_CLIENT client,
|
||||
PVIGEM_TARGET target,
|
||||
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> pNotificationRequestPayload
|
||||
)
|
||||
{
|
||||
int idx;
|
||||
DWORD error;
|
||||
|
||||
HANDLE waitObjects[2];
|
||||
|
||||
BOOL devIoResult[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
|
||||
DWORD lastIoError[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
|
||||
DWORD transferred[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
|
||||
OVERLAPPED lOverlapped[NOTIFICATION_OVERLAPPED_QUEUE_SIZE];
|
||||
|
||||
int currentOverlappedIdx;
|
||||
int futureOverlappedIdx;
|
||||
|
||||
memset(lOverlapped, 0, sizeof(lOverlapped));
|
||||
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
|
||||
lOverlapped[idx].hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
waitObjects[0] = target->cancelNotificationThreadEvent;
|
||||
|
||||
currentOverlappedIdx = 0;
|
||||
futureOverlappedIdx = NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1;
|
||||
|
||||
// Send out DeviceIOControl calls to wait for incoming feedback notifications. Use N pending requests to make sure that events are not lost even when application would flood FFB events.
|
||||
// The order of DeviceIoControl calls and GetOverlappedResult requests is important to ensure that feedback callback function is called in correct order (ie. FIFO buffer with FFB events).
|
||||
// Note! This loop doesn't call DevIo for the last lOverlapped item on purpose. The DO while loop does it as a first step (futureOverlappedIdx=NOTIFICATION_OVERLAPPED_QUEUE_SIZE-1 in the first loop round).
|
||||
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1; idx++)
|
||||
{
|
||||
devIoResult[idx] = DeviceIoControl(client->hBusDevice,
|
||||
(*pNotificationRequestPayload)[idx]->ioControlCode,
|
||||
(*pNotificationRequestPayload)[idx]->lpPayloadBuffer,
|
||||
(*pNotificationRequestPayload)[idx]->payloadBufferSize,
|
||||
(*pNotificationRequestPayload)[idx]->lpPayloadBuffer,
|
||||
(*pNotificationRequestPayload)[idx]->payloadBufferSize,
|
||||
&transferred[idx],
|
||||
&lOverlapped[idx]);
|
||||
|
||||
lastIoError[idx] = GetLastError();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Before reading data from "current overlapped request" then send a new DeviceIoControl request to wait for upcoming new FFB events (ring buffer of overlapped objects).
|
||||
devIoResult[futureOverlappedIdx] = DeviceIoControl(client->hBusDevice,
|
||||
(*pNotificationRequestPayload)[futureOverlappedIdx]->
|
||||
ioControlCode,
|
||||
(*pNotificationRequestPayload)[futureOverlappedIdx]->
|
||||
lpPayloadBuffer,
|
||||
(*pNotificationRequestPayload)[futureOverlappedIdx]->
|
||||
payloadBufferSize,
|
||||
(*pNotificationRequestPayload)[futureOverlappedIdx]->
|
||||
lpPayloadBuffer,
|
||||
(*pNotificationRequestPayload)[futureOverlappedIdx]->
|
||||
payloadBufferSize,
|
||||
&transferred[futureOverlappedIdx],
|
||||
&lOverlapped[futureOverlappedIdx]);
|
||||
|
||||
lastIoError[futureOverlappedIdx] = GetLastError();
|
||||
|
||||
// currentOverlappedIdx is an index to the "oldest" DeviceIOControl call, so it will receive the next FFB event in a FFB sequence (in case there are multiple FFB events coming in)
|
||||
if (!devIoResult[currentOverlappedIdx])
|
||||
{
|
||||
if (lastIoError[currentOverlappedIdx] == ERROR_IO_PENDING)
|
||||
{
|
||||
// DeviceIoControl is not yet completed to return all data. Wait for overlapped completion and thread cancellation events
|
||||
waitObjects[1] = lOverlapped[currentOverlappedIdx].hEvent;
|
||||
error = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE);
|
||||
if (error != (WAIT_OBJECT_0 + 1))
|
||||
break;
|
||||
// Cancel event signaled or error while waiting for events (maybe handles were closed?). Quit this thread worker
|
||||
|
||||
// At this point overlapped event was signaled by a device driver and data is ready and waiting for in a buffer. The next GetOverlappedResult call should return immediately.
|
||||
}
|
||||
else
|
||||
// Hmm... DeviceIoControl failed and is not just in async pending state. Quit the notification thread because the virtual controller may be in unknown state or device handles were closed
|
||||
break;
|
||||
}
|
||||
|
||||
if (GetOverlappedResult(client->hBusDevice, &lOverlapped[currentOverlappedIdx],
|
||||
&transferred[currentOverlappedIdx], TRUE) != 0)
|
||||
(*pNotificationRequestPayload)[currentOverlappedIdx]->ProcessNotificationRequest(client, target);
|
||||
|
||||
if (currentOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1)
|
||||
currentOverlappedIdx = 0;
|
||||
else
|
||||
currentOverlappedIdx++;
|
||||
|
||||
if (futureOverlappedIdx >= NOTIFICATION_OVERLAPPED_QUEUE_SIZE - 1)
|
||||
futureOverlappedIdx = 0;
|
||||
else
|
||||
futureOverlappedIdx++;
|
||||
}
|
||||
while (target->closingNotificationThreads != TRUE && target->Notification != nullptr);
|
||||
|
||||
for (idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
|
||||
if (lOverlapped[idx].hEvent)
|
||||
CloseHandle(lOverlapped[idx].hEvent);
|
||||
|
||||
// Caller created the unique_ptr object, but this thread worker function should delete the object because it is no longer needed (thread specific object)
|
||||
pNotificationRequestPayload.reset();
|
||||
}
|
||||
|
||||
VIGEM_ERROR vigem_target_x360_register_notification(
|
||||
PVIGEM_CLIENT vigem,
|
||||
PVIGEM_TARGET target,
|
||||
@@ -752,26 +570,70 @@ VIGEM_ERROR vigem_target_x360_register_notification(
|
||||
target->Notification = reinterpret_cast<FARPROC>(notification);
|
||||
target->NotificationUserData = userData;
|
||||
|
||||
if (target->cancelNotificationThreadEvent == 0)
|
||||
target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
else
|
||||
ResetEvent(target->cancelNotificationThreadEvent);
|
||||
if (target->cancelNotificationThreadEvent == nullptr)
|
||||
target->cancelNotificationThreadEvent = CreateEvent(
|
||||
nullptr,
|
||||
TRUE,
|
||||
FALSE,
|
||||
nullptr
|
||||
);
|
||||
else
|
||||
ResetEvent(target->cancelNotificationThreadEvent);
|
||||
|
||||
if(target->notificationThreadList == nullptr)
|
||||
target->notificationThreadList = std::make_unique<std::vector<std::thread>>();
|
||||
std::thread _async{
|
||||
[](
|
||||
PVIGEM_TARGET _Target,
|
||||
PVIGEM_CLIENT _Client,
|
||||
LPVOID _UserData)
|
||||
{
|
||||
DWORD transferred = 0;
|
||||
OVERLAPPED lOverlapped = {0};
|
||||
lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
target->closingNotificationThreads = FALSE;
|
||||
XUSB_REQUEST_NOTIFICATION xrn;
|
||||
XUSB_REQUEST_NOTIFICATION_INIT(&xrn, _Target->SerialNo);
|
||||
|
||||
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> payloadVector = std::make_unique<std::vector<std::unique_ptr<NotificationRequestPayload>>>();
|
||||
payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE);
|
||||
for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
|
||||
payloadVector->push_back(std::make_unique<NotificationRequestPayloadX360>(target->SerialNo));
|
||||
do
|
||||
{
|
||||
DeviceIoControl(
|
||||
_Client->hBusDevice,
|
||||
IOCTL_XUSB_REQUEST_NOTIFICATION,
|
||||
&xrn,
|
||||
xrn.Size,
|
||||
&xrn,
|
||||
xrn.Size,
|
||||
&transferred,
|
||||
&lOverlapped
|
||||
);
|
||||
|
||||
// Nowadays there is only one background thread listening for incoming FFB events, but there used to be more. This code still uses notificationThreadList vector even
|
||||
// when there is only one item in the vector. If it is someday find out that this logic needs more background threads then it is easy to do because the thread vector is already in place.
|
||||
//for (int i = 0; i < 1; i++)
|
||||
target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector)));
|
||||
if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0)
|
||||
{
|
||||
if (_Target->Notification == nullptr)
|
||||
{
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
reinterpret_cast<PFN_VIGEM_X360_NOTIFICATION>(_Target->Notification)(
|
||||
_Client, _Target, xrn.LargeMotor, xrn.SmallMotor, xrn.LedNumber, _UserData
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_OPERATION_ABORTED)
|
||||
{
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (TRUE);
|
||||
},
|
||||
target, vigem, userData
|
||||
};
|
||||
|
||||
_async.detach();
|
||||
|
||||
return VIGEM_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -801,45 +663,83 @@ VIGEM_ERROR vigem_target_ds4_register_notification(
|
||||
target->NotificationUserData = userData;
|
||||
|
||||
if (target->cancelNotificationThreadEvent == 0)
|
||||
target->cancelNotificationThreadEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
target->cancelNotificationThreadEvent = CreateEvent(
|
||||
nullptr,
|
||||
TRUE,
|
||||
FALSE,
|
||||
nullptr
|
||||
);
|
||||
else
|
||||
ResetEvent(target->cancelNotificationThreadEvent);
|
||||
|
||||
if (target->notificationThreadList == nullptr)
|
||||
target->notificationThreadList = std::make_unique<std::vector<std::thread>>();
|
||||
std::thread _async{
|
||||
[](
|
||||
PVIGEM_TARGET _Target,
|
||||
PVIGEM_CLIENT _Client,
|
||||
LPVOID _UserData)
|
||||
{
|
||||
DWORD transferred = 0;
|
||||
OVERLAPPED lOverlapped = {0};
|
||||
lOverlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
target->closingNotificationThreads = FALSE;
|
||||
DS4_REQUEST_NOTIFICATION ds4rn;
|
||||
DS4_REQUEST_NOTIFICATION_INIT(&ds4rn, _Target->SerialNo);
|
||||
|
||||
std::unique_ptr<std::vector<std::unique_ptr<NotificationRequestPayload>>> payloadVector = std::make_unique<std::vector<std::unique_ptr<NotificationRequestPayload>>>();
|
||||
payloadVector->reserve(NOTIFICATION_OVERLAPPED_QUEUE_SIZE);
|
||||
for (int idx = 0; idx < NOTIFICATION_OVERLAPPED_QUEUE_SIZE; idx++)
|
||||
payloadVector->push_back(std::make_unique<NotificationRequestPayloadDS4>(target->SerialNo));
|
||||
do
|
||||
{
|
||||
DeviceIoControl(
|
||||
_Client->hBusDevice,
|
||||
IOCTL_DS4_REQUEST_NOTIFICATION,
|
||||
&ds4rn,
|
||||
ds4rn.Size,
|
||||
&ds4rn,
|
||||
ds4rn.Size,
|
||||
&transferred,
|
||||
&lOverlapped
|
||||
);
|
||||
|
||||
//for (int i = 0; i < 1; i++)
|
||||
target->notificationThreadList->emplace_back(std::thread(&vigem_notification_thread_worker, vigem, target, std::move(payloadVector)));
|
||||
if (GetOverlappedResult(_Client->hBusDevice, &lOverlapped, &transferred, TRUE) != 0)
|
||||
{
|
||||
if (_Target->Notification == nullptr)
|
||||
{
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
reinterpret_cast<PFN_VIGEM_DS4_NOTIFICATION>(_Target->Notification)(
|
||||
_Client, _Target, ds4rn.Report.LargeMotor,
|
||||
ds4rn.Report.SmallMotor,
|
||||
ds4rn.Report.LightbarColor, _UserData
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_OPERATION_ABORTED)
|
||||
{
|
||||
CloseHandle(lOverlapped.hEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (TRUE);
|
||||
},
|
||||
target, vigem, userData
|
||||
};
|
||||
|
||||
_async.detach();
|
||||
|
||||
return VIGEM_ERROR_NONE;
|
||||
}
|
||||
|
||||
void vigem_target_x360_unregister_notification(PVIGEM_TARGET target)
|
||||
{
|
||||
target->closingNotificationThreads = TRUE;
|
||||
|
||||
{
|
||||
if (target->cancelNotificationThreadEvent != 0)
|
||||
SetEvent(target->cancelNotificationThreadEvent);
|
||||
|
||||
if (target->notificationThreadList != nullptr)
|
||||
{
|
||||
// Wait for completion of all notification threads before cleaning up target object and Notification function pointer (a thread may be in the middle of handling a notification request, so close it cleanly)
|
||||
std::for_each(target->notificationThreadList->begin(), target->notificationThreadList->end(), std::mem_fn(&std::thread::join));
|
||||
target->notificationThreadList.reset();
|
||||
target->notificationThreadList = nullptr;
|
||||
}
|
||||
|
||||
if (target->cancelNotificationThreadEvent != 0)
|
||||
|
||||
if (target->cancelNotificationThreadEvent != nullptr)
|
||||
{
|
||||
CloseHandle(target->cancelNotificationThreadEvent);
|
||||
target->cancelNotificationThreadEvent = 0;
|
||||
target->cancelNotificationThreadEvent = nullptr;
|
||||
}
|
||||
|
||||
target->Notification = nullptr;
|
||||
|
||||
BIN
setup/LICENSE.rtf
Normal file
BIN
setup/LICENSE.rtf
Normal file
Binary file not shown.
@@ -28,7 +28,7 @@
|
||||
<!-- basic product properties -->
|
||||
<Product Id="*" Name="Nefarius Virtual Gamepad Emulation Bus Driver" Language="1033" Version="$(var.VERSION)"
|
||||
Manufacturer="Nefarius Software Solutions e.U."
|
||||
UpgradeCode="b935b0e2-a67f-4f2f-88de-2457dbd70c6e">
|
||||
UpgradeCode="0A4A02DE-0BE3-4BF4-91F0-1EA47AD26881">
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<!-- use single MSI file only -->
|
||||
@@ -38,17 +38,18 @@
|
||||
<Icon Id="ViGEm.ico" SourceFile="ViGEm.ico" />
|
||||
<Property Id="ARPPRODUCTICON" Value="ViGEm.ico" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://github.com/ViGEm/ViGEmBus" />
|
||||
<Property Id="ARPNOMODIFY" Value="1" />
|
||||
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" />
|
||||
|
||||
<!-- always perform major upgrade and remove previous versions -->
|
||||
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
|
||||
<Upgrade Id="b935b0e2-a67f-4f2f-88de-2457dbd70c6e">
|
||||
<Upgrade Id="0A4A02DE-0BE3-4BF4-91F0-1EA47AD26881">
|
||||
<UpgradeVersion
|
||||
Minimum="1.0.0.0" Maximum="$(var.VERSION)"
|
||||
Property="PREVIOUSVERSIONSINSTALLED"
|
||||
IncludeMinimum="yes" IncludeMaximum="no" />
|
||||
</Upgrade>
|
||||
|
||||
<!-- don't allow downgrades -->
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
|
||||
<!-- https://stackoverflow.com/a/31991006 -->
|
||||
@@ -60,20 +61,20 @@
|
||||
|
||||
<!-- https://stackoverflow.com/a/23061358 -->
|
||||
<Condition Message="This application can only be installed on Windows 10.">
|
||||
<![CDATA[WIN10FOUND]]>
|
||||
<![CDATA[Installed OR WIN10FOUND]]>
|
||||
</Condition>
|
||||
|
||||
<!-- write version value to registry -->
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Component Id="RegistryEntries" Guid="85C87E47-E2C7-4684-A3FB-6F7853A86B41">
|
||||
<RegistryKey Root="HKLM"
|
||||
Key="SOFTWARE\Nefarius Software Solutions e.U.\ViGEm Bus Driver"
|
||||
Action="createAndRemoveOnUninstall">
|
||||
Key="SOFTWARE\Nefarius Software Solutions e.U.\ViGEm Bus Driver">
|
||||
<RegistryValue Type="string" Name="Version" Value="$(var.VERSION)" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- main feature are the driver files and some version registry values -->
|
||||
<Feature Id="ProductFeature" Title="Nefarius Virtual Gamepad Emulation Bus Driver" Level="1">
|
||||
<ComponentGroupRef Id="ProductComponents" />
|
||||
<ComponentRef Id="RegistryEntries" />
|
||||
@@ -92,7 +93,7 @@
|
||||
<!-- build removal command -->
|
||||
<CustomAction Id="DevconRemovePropertyAssign"
|
||||
Property="DevconRemoveQuiet"
|
||||
Value=""[INSTALLFOLDER]devcon.exe" remove "Nefarius\ViGEmBus\Gen1""
|
||||
Value=""[INSTALLFOLDER]devcon.exe" /r remove "Nefarius\ViGEmBus\Gen1""
|
||||
Execute="immediate" />
|
||||
|
||||
<!-- execute removal with suppressed UI -->
|
||||
@@ -106,13 +107,23 @@
|
||||
<Custom Action="DevconInstallQuiet" Before="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
|
||||
<Custom Action='DevconRemoveQuiet' After='InstallInitialize'>REMOVE="ALL"</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<!-- use LICENSE as EULA, not technically an EULA but for now it has to do -->
|
||||
<WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)LICENSE.rtf" />
|
||||
|
||||
<!-- use minimalistic UI with EULA approval -->
|
||||
<UIRef Id="WixUI_Minimal" />
|
||||
|
||||
</Product>
|
||||
|
||||
<!-- build program files directory -->
|
||||
<Fragment>
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="$(var.PlatformProgramFilesFolder)">
|
||||
<Directory Id="INSTALLFOLDER" Name="Nefarius Virtual Gamepad Emulation Bus Driver" />
|
||||
<!-- the "e.U." is butchered so omitted -->
|
||||
<Directory Id="NSS" Name="Nefarius Software Solutions">
|
||||
<Directory Id="INSTALLFOLDER" Name="Virtual Gamepad Emulation Bus Driver" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Fragment>
|
||||
@@ -126,21 +137,19 @@
|
||||
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.sys" />
|
||||
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.inf" />
|
||||
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\ViGEmBus.cat" />
|
||||
<File Name="WdfCoinstaller01009.dll" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\WdfCoinstaller01009.dll" />
|
||||
<File Name="devcon.exe" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\devcon.exe" />
|
||||
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)\drivers\devcon-LICENSE" />
|
||||
<File Name="LICENSE" Source="$(var.SolutionDir)\LICENSE" />
|
||||
<?else ?>
|
||||
<!-- CI build -->
|
||||
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.sys" />
|
||||
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.inf" />
|
||||
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.cat" />
|
||||
<File Name="WdfCoinstaller01009.dll" Source="$(var.SolutionDir)\bin\$(var.ArchDir)\ViGEmBus\WdfCoinstaller01009.dll" />
|
||||
<File Name="devcon.exe" Source="$(var.SolutionDir)\drivers\$(var.ArchDir)\devcon.exe" />
|
||||
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)\drivers\devcon-LICENSE" />
|
||||
<File Name="LICENSE" Source="$(var.SolutionDir)\LICENSE" />
|
||||
<File Name="ViGEmBus.sys" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.sys" />
|
||||
<File Name="ViGEmBus.inf" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.inf" />
|
||||
<File Name="ViGEmBus.cat" Source="$(var.SolutionDir)bin\$(var.ArchDir)\ViGEmBus\ViGEmBus.cat" />
|
||||
<File Name="devcon.exe" Source="$(var.SolutionDir)drivers\$(var.ArchDir)\devcon.exe" />
|
||||
<File Name="devcon-LICENSE" Source="$(var.SolutionDir)drivers\devcon-LICENSE" />
|
||||
<File Name="LICENSE" Source="$(var.SolutionDir)LICENSE" />
|
||||
<?endif ?>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
</Wix>
|
||||
|
||||
@@ -35,11 +35,25 @@
|
||||
<Content Include="ViGEm.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixUIExtension">
|
||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||
<Name>WixUIExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixUtilExtension">
|
||||
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||
<Name>WixUtilExtension</Name>
|
||||
</WixExtension>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\sys\ViGEmBus.vcxproj">
|
||||
<Name>ViGEmBus</Name>
|
||||
<Project>{040101b0-ee5c-4ef1-99ee-9f81c795c001}</Project>
|
||||
<Private>True</Private>
|
||||
<DoNotHarvest>True</DoNotHarvest>
|
||||
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
|
||||
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||
|
||||
@@ -44,7 +44,7 @@ void* operator new
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
}
|
||||
|
||||
void* operator new[]
|
||||
@@ -52,7 +52,7 @@ void* operator new[]
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
}
|
||||
|
||||
void operator delete
|
||||
@@ -107,7 +107,7 @@ void* __CRTDECL operator new
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
}
|
||||
|
||||
void* __CRTDECL operator new[]
|
||||
@@ -115,7 +115,7 @@ void* __CRTDECL operator new[]
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
return ExAllocatePoolWithTag(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
return ExAllocatePoolZero(NonPagedPoolNx, size, cpp_pool_tag);
|
||||
}
|
||||
|
||||
void __CRTDECL operator delete
|
||||
|
||||
545
sys/Driver.cpp
545
sys/Driver.cpp
@@ -34,7 +34,8 @@
|
||||
|
||||
|
||||
#include "Driver.h"
|
||||
#include "driver.tmh"
|
||||
#include "trace.h"
|
||||
#include "Driver.tmh"
|
||||
#include <wdmguid.h>
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
@@ -45,7 +46,7 @@
|
||||
#pragma alloc_text (PAGE, Bus_EvtDriverContextCleanup)
|
||||
#endif
|
||||
|
||||
|
||||
#include "Queue.hpp"
|
||||
#include "EmulationTargetPDO.hpp"
|
||||
#include "XusbPdo.hpp"
|
||||
#include "Ds4Pdo.hpp"
|
||||
@@ -63,40 +64,42 @@ EXTERN_C_START
|
||||
//
|
||||
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
WDF_DRIVER_CONFIG config;
|
||||
NTSTATUS status;
|
||||
WDFDRIVER driver;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
WDF_DRIVER_CONFIG config;
|
||||
NTSTATUS status;
|
||||
WDFDRIVER driver;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
|
||||
KdPrint((DRIVERNAME "Virtual Gamepad Emulation Bus Driver [built: %s %s]\n", __DATE__, __TIME__));
|
||||
KdPrint((DRIVERNAME "Virtual Gamepad Emulation Bus Driver [built: %s %s]\n", __DATE__, __TIME__));
|
||||
|
||||
//
|
||||
// Initialize WPP Tracing
|
||||
//
|
||||
WPP_INIT_TRACING(DriverObject, RegistryPath);
|
||||
//
|
||||
// Initialize WPP Tracing
|
||||
//
|
||||
WPP_INIT_TRACING(DriverObject, RegistryPath);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Loading Virtual Gamepad Emulation Bus Driver [built: %s %s]",
|
||||
__DATE__, __TIME__);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Loading Virtual Gamepad Emulation Bus Driver"
|
||||
);
|
||||
|
||||
//
|
||||
// Register cleanup callback
|
||||
//
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.EvtCleanupCallback = Bus_EvtDriverContextCleanup;
|
||||
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
||||
|
||||
WDF_DRIVER_CONFIG_INIT(&config, Bus_EvtDeviceAdd);
|
||||
//
|
||||
// Register cleanup callback
|
||||
//
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.EvtCleanupCallback = Bus_EvtDriverContextCleanup;
|
||||
|
||||
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &driver);
|
||||
WDF_DRIVER_CONFIG_INIT(&config, Bus_EvtDeviceAdd);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
WPP_CLEANUP(DriverObject);
|
||||
KdPrint((DRIVERNAME "WdfDriverCreate failed with status 0x%x\n", status));
|
||||
}
|
||||
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &driver);
|
||||
|
||||
return status;
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
WPP_CLEANUP(DriverObject);
|
||||
KdPrint((DRIVERNAME "WdfDriverCreate failed with status 0x%x\n", status));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -104,168 +107,168 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry
|
||||
//
|
||||
NTSTATUS Bus_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
|
||||
{
|
||||
WDF_CHILD_LIST_CONFIG config;
|
||||
NTSTATUS status;
|
||||
WDFDEVICE device;
|
||||
WDF_IO_QUEUE_CONFIG queueConfig;
|
||||
PNP_BUS_INFORMATION busInfo;
|
||||
WDFQUEUE queue;
|
||||
WDF_FILEOBJECT_CONFIG foConfig;
|
||||
WDF_OBJECT_ATTRIBUTES fdoAttributes;
|
||||
WDF_OBJECT_ATTRIBUTES fileHandleAttributes;
|
||||
PFDO_DEVICE_DATA pFDOData;
|
||||
PWSTR pSymbolicNameList;
|
||||
WDF_CHILD_LIST_CONFIG config;
|
||||
NTSTATUS status;
|
||||
WDFDEVICE device;
|
||||
WDF_IO_QUEUE_CONFIG queueConfig;
|
||||
PNP_BUS_INFORMATION busInfo;
|
||||
WDFQUEUE queue;
|
||||
WDF_FILEOBJECT_CONFIG foConfig;
|
||||
WDF_OBJECT_ATTRIBUTES fdoAttributes;
|
||||
WDF_OBJECT_ATTRIBUTES fileHandleAttributes;
|
||||
PFDO_DEVICE_DATA pFDOData;
|
||||
PWSTR pSymbolicNameList;
|
||||
|
||||
UNREFERENCED_PARAMETER(Driver);
|
||||
UNREFERENCED_PARAMETER(Driver);
|
||||
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
#pragma region Check for duplicated FDO
|
||||
|
||||
//
|
||||
// Note: this could be avoided if converted to non-PNP driver
|
||||
// and use of named device object. Food for thought for future.
|
||||
//
|
||||
|
||||
status = IoGetDeviceInterfaces(
|
||||
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
|
||||
NULL,
|
||||
0, // Important!
|
||||
&pSymbolicNameList
|
||||
);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
const bool deviceAlreadyExists = (0 != *pSymbolicNameList);
|
||||
ExFreePool(pSymbolicNameList);
|
||||
//
|
||||
// Note: this could be avoided if converted to non-PNP driver
|
||||
// and use of named device object. Food for thought for future.
|
||||
//
|
||||
|
||||
if (deviceAlreadyExists)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"Device with interface GUID {%!GUID!} already exists (%ws)",
|
||||
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
|
||||
pSymbolicNameList
|
||||
);
|
||||
status = IoGetDeviceInterfaces(
|
||||
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
|
||||
NULL,
|
||||
0, // Important!
|
||||
&pSymbolicNameList
|
||||
);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
const bool deviceAlreadyExists = (0 != *pSymbolicNameList);
|
||||
ExFreePool(pSymbolicNameList);
|
||||
|
||||
return STATUS_RESOURCE_IN_USE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_DRIVER,
|
||||
"IoGetDeviceInterfaces failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
if (deviceAlreadyExists)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"Device with interface GUID {%!GUID!} already exists (%ws)",
|
||||
&GUID_DEVINTERFACE_BUSENUM_VIGEM,
|
||||
pSymbolicNameList
|
||||
);
|
||||
|
||||
return STATUS_RESOURCE_IN_USE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_DRIVER,
|
||||
"IoGetDeviceInterfaces failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
|
||||
// More than one process may talk to the bus at the same time
|
||||
WdfDeviceInitSetExclusive(DeviceInit, FALSE);
|
||||
// Bus is power policy owner over all PDOs
|
||||
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE);
|
||||
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
|
||||
// More than one process may talk to the bus at the same time
|
||||
WdfDeviceInitSetExclusive(DeviceInit, FALSE);
|
||||
// Bus is power policy owner over all PDOs
|
||||
WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE);
|
||||
|
||||
#pragma region Prepare child list
|
||||
|
||||
WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo);
|
||||
WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo);
|
||||
|
||||
config.EvtChildListIdentificationDescriptionCompare = EmulationTargetPDO::EvtChildListIdentificationDescriptionCompare;
|
||||
config.EvtChildListIdentificationDescriptionCompare = EmulationTargetPDO::EvtChildListIdentificationDescriptionCompare;
|
||||
|
||||
WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
|
||||
WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Assign File Object Configuration
|
||||
|
||||
WDF_FILEOBJECT_CONFIG_INIT(&foConfig, Bus_DeviceFileCreate, Bus_FileClose, NULL);
|
||||
WDF_FILEOBJECT_CONFIG_INIT(&foConfig, Bus_DeviceFileCreate, Bus_FileClose, NULL);
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileHandleAttributes, FDO_FILE_DATA);
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileHandleAttributes, FDO_FILE_DATA);
|
||||
|
||||
WdfDeviceInitSetFileObjectConfig(DeviceInit, &foConfig, &fileHandleAttributes);
|
||||
WdfDeviceInitSetFileObjectConfig(DeviceInit, &foConfig, &fileHandleAttributes);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Create FDO
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA);
|
||||
|
||||
status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
|
||||
status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"WdfDeviceCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"WdfDeviceCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
pFDOData = FdoGetData(device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
pFDOData = FdoGetData(device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
pFDOData->InterfaceReferenceCounter = 0;
|
||||
pFDOData->NextSessionId = FDO_FIRST_SESSION_ID;
|
||||
pFDOData->InterfaceReferenceCounter = 0;
|
||||
pFDOData->NextSessionId = FDO_FIRST_SESSION_ID;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Create default I/O queue for FDO
|
||||
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
|
||||
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
|
||||
|
||||
queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;
|
||||
queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl;
|
||||
|
||||
__analysis_assume(queueConfig.EvtIoStop != 0);
|
||||
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
|
||||
__analysis_assume(queueConfig.EvtIoStop == 0);
|
||||
__analysis_assume(queueConfig.EvtIoStop != 0);
|
||||
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
|
||||
__analysis_assume(queueConfig.EvtIoStop == 0);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"WdfIoQueueCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"WdfIoQueueCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Expose FDO interface
|
||||
|
||||
status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BUSENUM_VIGEM, NULL);
|
||||
status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BUSENUM_VIGEM, NULL);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Set bus information
|
||||
|
||||
busInfo.BusTypeGuid = GUID_BUS_TYPE_USB;
|
||||
busInfo.LegacyBusType = PNPBus;
|
||||
busInfo.BusNumber = 0;
|
||||
busInfo.BusTypeGuid = GUID_BUS_TYPE_USB;
|
||||
busInfo.LegacyBusType = PNPBus;
|
||||
busInfo.BusNumber = 0;
|
||||
|
||||
WdfDeviceSetBusInformationForChildren(device, &busInfo);
|
||||
WdfDeviceSetBusInformationForChildren(device, &busInfo);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
return status;
|
||||
}
|
||||
|
||||
// Gets called when the user-land process (or kernel driver) exits or closes the handle,
|
||||
@@ -274,60 +277,60 @@ NTSTATUS Bus_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
Bus_DeviceFileCreate(
|
||||
_In_ WDFDEVICE Device,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ WDFFILEOBJECT FileObject
|
||||
_In_ WDFDEVICE Device,
|
||||
_In_ WDFREQUEST Request,
|
||||
_In_ WDFFILEOBJECT FileObject
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
PFDO_FILE_DATA pFileData = NULL;
|
||||
PFDO_DEVICE_DATA pFDOData = NULL;
|
||||
LONG refCount = 0;
|
||||
LONG sessionId = 0;
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
PFDO_FILE_DATA pFileData = NULL;
|
||||
PFDO_DEVICE_DATA pFDOData = NULL;
|
||||
LONG refCount = 0;
|
||||
LONG sessionId = 0;
|
||||
|
||||
UNREFERENCED_PARAMETER(Request);
|
||||
UNREFERENCED_PARAMETER(Request);
|
||||
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
pFileData = FileObjectGetData(FileObject);
|
||||
pFileData = FileObjectGetData(FileObject);
|
||||
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
|
||||
FileObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFDOData = FdoGetData(Device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
status = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
refCount = InterlockedIncrement(&pFDOData->InterfaceReferenceCounter);
|
||||
sessionId = InterlockedIncrement(&pFDOData->NextSessionId);
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
|
||||
FileObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
pFDOData = FdoGetData(Device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
status = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
refCount = InterlockedIncrement(&pFDOData->InterfaceReferenceCounter);
|
||||
sessionId = InterlockedIncrement(&pFDOData->NextSessionId);
|
||||
|
||||
pFileData->SessionId = sessionId;
|
||||
status = STATUS_SUCCESS;
|
||||
pFileData->SessionId = sessionId;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"File/session id = %d, device ref. count = %d",
|
||||
(int)sessionId, (int)refCount);
|
||||
}
|
||||
}
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"File/session id = %d, device ref. count = %d",
|
||||
(int)sessionId, (int)refCount);
|
||||
}
|
||||
}
|
||||
|
||||
WdfRequestComplete(Request, status);
|
||||
WdfRequestComplete(Request, status);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -336,139 +339,139 @@ Bus_DeviceFileCreate(
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
Bus_FileClose(
|
||||
WDFFILEOBJECT FileObject
|
||||
WDFFILEOBJECT FileObject
|
||||
)
|
||||
{
|
||||
WDFDEVICE device;
|
||||
WDFDEVICE hChild;
|
||||
NTSTATUS status;
|
||||
WDFCHILDLIST list;
|
||||
WDF_CHILD_LIST_ITERATOR iterator;
|
||||
WDF_CHILD_RETRIEVE_INFO childInfo;
|
||||
PDO_IDENTIFICATION_DESCRIPTION description;
|
||||
PFDO_FILE_DATA pFileData = NULL;
|
||||
PFDO_DEVICE_DATA pFDOData = NULL;
|
||||
LONG refCount = 0;
|
||||
WDFDEVICE device;
|
||||
WDFDEVICE hChild;
|
||||
NTSTATUS status;
|
||||
WDFCHILDLIST list;
|
||||
WDF_CHILD_LIST_ITERATOR iterator;
|
||||
WDF_CHILD_RETRIEVE_INFO childInfo;
|
||||
PDO_IDENTIFICATION_DESCRIPTION description;
|
||||
PFDO_FILE_DATA pFileData = NULL;
|
||||
PFDO_DEVICE_DATA pFDOData = NULL;
|
||||
LONG refCount = 0;
|
||||
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
// Check common context
|
||||
pFileData = FileObjectGetData(FileObject);
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
|
||||
FileObject);
|
||||
return;
|
||||
}
|
||||
// Check common context
|
||||
pFileData = FileObjectGetData(FileObject);
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"FileObjectGetData failed to return file object from WDFFILEOBJECT 0x%p",
|
||||
FileObject);
|
||||
return;
|
||||
}
|
||||
|
||||
device = WdfFileObjectGetDevice(FileObject);
|
||||
device = WdfFileObjectGetDevice(FileObject);
|
||||
|
||||
pFDOData = FdoGetData(device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
status = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
refCount = InterlockedDecrement(&pFDOData->InterfaceReferenceCounter);
|
||||
pFDOData = FdoGetData(device);
|
||||
if (pFDOData == NULL)
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"FdoGetData failed");
|
||||
status = STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
refCount = InterlockedDecrement(&pFDOData->InterfaceReferenceCounter);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Device ref. count = %d",
|
||||
(int)refCount);
|
||||
}
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Device ref. count = %d",
|
||||
(int)refCount);
|
||||
}
|
||||
|
||||
list = WdfFdoGetDefaultChildList(device);
|
||||
list = WdfFdoGetDefaultChildList(device);
|
||||
|
||||
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren);
|
||||
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrievePresentChildren);
|
||||
|
||||
WdfChildListBeginIteration(list, &iterator);
|
||||
WdfChildListBeginIteration(list, &iterator);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);
|
||||
WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
|
||||
for (;;)
|
||||
{
|
||||
WDF_CHILD_RETRIEVE_INFO_INIT(&childInfo, &description.Header);
|
||||
WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
|
||||
|
||||
status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo);
|
||||
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
status = WdfChildListRetrieveNextDevice(list, &iterator, &hChild, &childInfo);
|
||||
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
// TRACE_DRIVER,
|
||||
// "PDO properties: status = %!STATUS!, pdoPID = %d, curPID = %d, pdoSID = %d, curSID = %d, internal = %d",
|
||||
// (int)childInfo.Status,
|
||||
// (int)description.OwnerProcessId,
|
||||
// (int)CURRENT_PROCESS_ID(),
|
||||
// (int)description.SessionId,
|
||||
// (int)pFileData->SessionId,
|
||||
// (int)description.OwnerIsDriver
|
||||
//);
|
||||
//TraceVerbose(
|
||||
// TRACE_DRIVER,
|
||||
// "PDO properties: status = %!STATUS!, pdoPID = %d, curPID = %d, pdoSID = %d, curSID = %d, internal = %d",
|
||||
// (int)childInfo.Status,
|
||||
// (int)description.OwnerProcessId,
|
||||
// (int)CURRENT_PROCESS_ID(),
|
||||
// (int)description.SessionId,
|
||||
// (int)pFileData->SessionId,
|
||||
// (int)description.OwnerIsDriver
|
||||
//);
|
||||
|
||||
// Only unplug devices with matching session id
|
||||
if (childInfo.Status == WdfChildListRetrieveDeviceSuccess
|
||||
&& description.SessionId == pFileData->SessionId)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Unplugging device with serial %d",
|
||||
description.SerialNo);
|
||||
// Only unplug devices with matching session id
|
||||
if (childInfo.Status == WdfChildListRetrieveDeviceSuccess
|
||||
&& description.SessionId == pFileData->SessionId)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DRIVER,
|
||||
"Unplugging device with serial %d",
|
||||
description.SerialNo);
|
||||
|
||||
// "Unplug" child
|
||||
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DRIVER,
|
||||
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
}
|
||||
}
|
||||
// "Unplug" child
|
||||
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_DRIVER,
|
||||
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WdfChildListEndIteration(list, &iterator);
|
||||
WdfChildListEndIteration(list, &iterator);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
}
|
||||
|
||||
VOID
|
||||
Bus_EvtDriverContextCleanup(
|
||||
_In_ WDFOBJECT DriverObject
|
||||
_In_ WDFOBJECT DriverObject
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
|
||||
Free all the resources allocated in DriverEntry.
|
||||
Free all the resources allocated in DriverEntry.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - handle to a WDF Driver object.
|
||||
DriverObject - handle to a WDF Driver object.
|
||||
|
||||
Return Value:
|
||||
|
||||
VOID.
|
||||
VOID.
|
||||
|
||||
--*/
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
|
||||
PAGED_CODE();
|
||||
PAGED_CODE();
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
|
||||
|
||||
//
|
||||
// Stop WPP Tracing
|
||||
//
|
||||
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
|
||||
//
|
||||
// Stop WPP Tracing
|
||||
//
|
||||
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -35,15 +35,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "trace.h"
|
||||
#pragma warning(disable:5040)
|
||||
#include <DmfModules.Library.h>
|
||||
#pragma warning(default:5040)
|
||||
#include <ntddk.h>
|
||||
#include <wdf.h>
|
||||
#define NTSTRSAFE_LIB
|
||||
#include <ntstrsafe.h>
|
||||
#include <initguid.h>
|
||||
#include <ViGEm/km/BusShared.h>
|
||||
#include "Queue.hpp"
|
||||
|
||||
|
||||
|
||||
#pragma region Macros
|
||||
|
||||
269
sys/Ds4Pdo.cpp
269
sys/Ds4Pdo.cpp
@@ -44,8 +44,8 @@
|
||||
PCWSTR ViGEm::Bus::Targets::EmulationTargetDS4::_deviceDescription = L"Virtual DualShock 4 Controller";
|
||||
|
||||
ViGEm::Bus::Targets::EmulationTargetDS4::EmulationTargetDS4(ULONG Serial, LONG SessionId, USHORT VendorId,
|
||||
USHORT ProductId) : EmulationTargetPDO(
|
||||
Serial, SessionId, VendorId, ProductId)
|
||||
USHORT ProductId) : EmulationTargetPDO(
|
||||
Serial, SessionId, VendorId, ProductId)
|
||||
{
|
||||
this->_TargetType = DualShock4Wired;
|
||||
this->_UsbConfigurationDescriptionSize = DS4_DESCRIPTOR_SIZE;
|
||||
@@ -72,7 +72,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = RtlUnicodeStringInit(DeviceDescription, _deviceDescription);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"RtlUnicodeStringInit failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -86,7 +86,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -101,7 +101,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -114,7 +114,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfPdoInitAddCompatibleID (#01) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -126,7 +126,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfPdoInitAddCompatibleID (#02) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -138,7 +138,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfPdoInitAddCompatibleID (#03) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -200,10 +200,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfTimerCreate failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfTimerCreate failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -224,10 +224,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfDriverOpenParametersRegistryKey failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfDriverOpenParametersRegistryKey failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -244,10 +244,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -264,10 +264,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -285,10 +285,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfRegistryCreateKey failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -304,14 +304,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_DS4,
|
||||
"MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
this->_TargetMacAddress.Vendor0,
|
||||
this->_TargetMacAddress.Vendor1,
|
||||
this->_TargetMacAddress.Vendor2,
|
||||
this->_TargetMacAddress.Nic0,
|
||||
this->_TargetMacAddress.Nic1,
|
||||
this->_TargetMacAddress.Nic2);
|
||||
TRACE_DS4,
|
||||
"MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
this->_TargetMacAddress.Vendor0,
|
||||
this->_TargetMacAddress.Vendor1,
|
||||
this->_TargetMacAddress.Vendor2,
|
||||
this->_TargetMacAddress.Nic0,
|
||||
this->_TargetMacAddress.Nic1,
|
||||
this->_TargetMacAddress.Nic2);
|
||||
|
||||
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
{
|
||||
@@ -326,19 +326,19 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfRegistryAssignValue failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfRegistryAssignValue failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfRegistryQueryValue failed with status %!STATUS!",
|
||||
status);
|
||||
TraceError(
|
||||
TRACE_DS4,
|
||||
"WdfRegistryQueryValue failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -428,20 +428,20 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SelectConfiguration(PURB Urb)
|
||||
if (Urb->UrbHeader.Length < DS4_CONFIGURATION_SIZE)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor");
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Invalid ConfigurationDescriptor");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectConfiguration.Interface;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TRACE_DS4,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
static_cast<int>(pInfo->Length),
|
||||
static_cast<int>(pInfo->InterfaceNumber),
|
||||
static_cast<int>(pInfo->AlternateSetting),
|
||||
pInfo->NumberOfPipes);
|
||||
TraceVerbose(
|
||||
TRACE_DS4,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
static_cast<int>(pInfo->Length),
|
||||
static_cast<int>(pInfo->InterfaceNumber),
|
||||
static_cast<int>(pInfo->AlternateSetting),
|
||||
pInfo->NumberOfPipes);
|
||||
|
||||
pInfo->Class = 0x03; // HID
|
||||
pInfo->SubClass = 0x00;
|
||||
@@ -478,10 +478,10 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
|
||||
{
|
||||
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST* pRequest = &Urb->UrbControlVendorClassRequest;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_CLASS_INTERFACE");
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> TransferFlags = 0x%X, Request = 0x%X, Value = 0x%X, Index = 0x%X, BufLen = %d",
|
||||
pRequest->TransferFlags,
|
||||
@@ -497,7 +497,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
|
||||
UCHAR reportId = hid_get_report_id(pRequest);
|
||||
UCHAR reportType = hid_get_report_type(pRequest);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> >> GET_REPORT(%d): %d",
|
||||
reportType, reportId);
|
||||
@@ -584,7 +584,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbClassInterface(PURB Urb)
|
||||
UCHAR reportId = hid_get_report_id(pRequest);
|
||||
UCHAR reportType = hid_get_report_type(pRequest);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> >> SET_REPORT(%d): %d",
|
||||
reportType, reportId);
|
||||
@@ -882,7 +882,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetDescriptorFromInterface(
|
||||
|
||||
struct _URB_CONTROL_DESCRIPTOR_REQUEST* pRequest = &Urb->UrbControlDescriptorRequest;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> _URB_CONTROL_DESCRIPTOR_REQUEST: Buffer Length %d",
|
||||
pRequest->TransferBufferLength);
|
||||
@@ -910,7 +910,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbSelectInterface(PURB Urb)
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PURB Urb)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"Index = %d",
|
||||
Urb->UrbControlDescriptorRequest.Index);
|
||||
@@ -932,7 +932,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"LanguageId = 0x%X",
|
||||
Urb->UrbControlDescriptorRequest.LanguageId);
|
||||
@@ -963,7 +963,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"LanguageId = 0x%X",
|
||||
Urb->UrbControlDescriptorRequest.LanguageId);
|
||||
@@ -999,14 +999,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbGetStringDescriptorType(PUR
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request)
|
||||
{
|
||||
NTSTATUS status;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
WDFREQUEST notifyRequest;
|
||||
|
||||
|
||||
// Data coming FROM us TO higher driver
|
||||
if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN
|
||||
&& pTransfer->PipeHandle == reinterpret_cast<USBD_PIPE_HANDLE>(0xFFFF0084))
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> Incoming request, queuing...");
|
||||
|
||||
@@ -1023,16 +1023,15 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_UR
|
||||
static_cast<PUCHAR>(pTransfer->TransferBuffer) + DS4_OUTPUT_BUFFER_OFFSET,
|
||||
DS4_OUTPUT_BUFFER_LENGTH);
|
||||
|
||||
// Notify user-mode process that new data is available
|
||||
status = WdfIoQueueRetrieveNextRequest(this->_PendingNotificationRequests, ¬ifyRequest);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
if (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(
|
||||
this->_PendingNotificationRequests,
|
||||
¬ifyRequest)))
|
||||
{
|
||||
PDS4_REQUEST_NOTIFICATION notify = NULL;
|
||||
PDS4_REQUEST_NOTIFICATION notify = nullptr;
|
||||
|
||||
status = WdfRequestRetrieveOutputBuffer(
|
||||
notifyRequest,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION),
|
||||
notifyRequest,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION),
|
||||
reinterpret_cast<PVOID*>(¬ify),
|
||||
nullptr
|
||||
);
|
||||
@@ -1044,17 +1043,45 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::UsbBulkOrInterruptTransfer(_UR
|
||||
notify->SerialNo = this->_SerialNo;
|
||||
notify->Report = this->_OutputReport;
|
||||
|
||||
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
|
||||
notify,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION)
|
||||
);
|
||||
|
||||
WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_USBPDO,
|
||||
"WdfRequestRetrieveOutputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PVOID clientBuffer, contextBuffer;
|
||||
|
||||
if (NT_SUCCESS(DMF_BufferQueue_Fetch(
|
||||
this->_UsbInterruptOutBufferQueue,
|
||||
&clientBuffer,
|
||||
&contextBuffer
|
||||
)))
|
||||
{
|
||||
RtlCopyMemory(
|
||||
clientBuffer,
|
||||
&this->_OutputReport,
|
||||
DS4_OUTPUT_BUFFER_LENGTH
|
||||
);
|
||||
|
||||
*static_cast<size_t*>(contextBuffer) = DS4_OUTPUT_BUFFER_LENGTH;
|
||||
|
||||
TraceVerbose(TRACE_USBPDO, "Queued %Iu bytes", DS4_OUTPUT_BUFFER_LENGTH);
|
||||
|
||||
DMF_BufferQueue_Enqueue(this->_UsbInterruptOutBufferQueue, clientBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1090,9 +1117,9 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFREQUEST usbRequest;
|
||||
|
||||
|
||||
/*
|
||||
* The logic here is unusual to keep backwards compatibility with the
|
||||
* The logic here is unusual to keep backwards compatibility with the
|
||||
* original API that didn't allow submitting the full report.
|
||||
*/
|
||||
|
||||
@@ -1121,13 +1148,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
|
||||
* Skip first byte as it contains the never changing report ID
|
||||
*/
|
||||
|
||||
//
|
||||
// "Old" API which only allows to update partial report
|
||||
//
|
||||
//
|
||||
// "Old" API which only allows to update partial report
|
||||
//
|
||||
if (pSubmit->Size == sizeof(DS4_SUBMIT_REPORT))
|
||||
{
|
||||
TraceDbg(TRACE_DS4, "Received DS4_SUBMIT_REPORT update");
|
||||
|
||||
TraceVerbose(TRACE_DS4, "Received DS4_SUBMIT_REPORT update");
|
||||
|
||||
RtlCopyBytes(
|
||||
&this->_Report[1],
|
||||
&(static_cast<PDS4_SUBMIT_REPORT>(NewReport))->Report,
|
||||
@@ -1140,15 +1167,15 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
|
||||
//
|
||||
if (pSubmit->Size == sizeof(DS4_SUBMIT_REPORT_EX))
|
||||
{
|
||||
TraceDbg(TRACE_DS4, "Received DS4_SUBMIT_REPORT_EX update");
|
||||
|
||||
TraceVerbose(TRACE_DS4, "Received DS4_SUBMIT_REPORT_EX update");
|
||||
|
||||
RtlCopyBytes(
|
||||
&this->_Report[1],
|
||||
&(static_cast<PDS4_SUBMIT_REPORT_EX>(NewReport))->Report,
|
||||
sizeof((static_cast<PDS4_SUBMIT_REPORT_EX>(NewReport))->Report)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (buffer)
|
||||
RtlCopyBytes(buffer, this->_Report, DS4_REPORT_SIZE);
|
||||
|
||||
@@ -1160,8 +1187,8 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
|
||||
|
||||
VOID ViGEm::Bus::Targets::EmulationTargetDS4::ReverseByteArray(PUCHAR Array, INT Length)
|
||||
{
|
||||
const auto s = static_cast<PUCHAR>(ExAllocatePoolWithTag(
|
||||
NonPagedPool,
|
||||
const auto s = static_cast<PUCHAR>(ExAllocatePoolZero(
|
||||
NonPagedPoolNx,
|
||||
sizeof(UCHAR) * Length,
|
||||
'U4SD'
|
||||
));
|
||||
@@ -1193,6 +1220,74 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::GenerateRandomMacAddress(PMAC_ADDR
|
||||
Address->Nic2 = RtlRandomEx(&seed) % 0xFF;
|
||||
}
|
||||
|
||||
void ViGEm::Bus::Targets::EmulationTargetDS4::ProcessPendingNotification(WDFQUEUE Queue)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFREQUEST request;
|
||||
PVOID clientBuffer, contextBuffer;
|
||||
PDS4_REQUEST_NOTIFICATION notify = nullptr;
|
||||
|
||||
FuncEntry(TRACE_DS4);
|
||||
|
||||
//
|
||||
// Loop through and drain all queued requests until buffer is empty
|
||||
//
|
||||
while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(Queue, &request)))
|
||||
{
|
||||
status = DMF_BufferQueue_Dequeue(
|
||||
this->_UsbInterruptOutBufferQueue,
|
||||
&clientBuffer,
|
||||
&contextBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Shouldn't happen, but if so, error out
|
||||
//
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
//
|
||||
// Don't requeue request as we maya be out of order now
|
||||
//
|
||||
WdfRequestComplete(request, status);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(WdfRequestRetrieveOutputBuffer(
|
||||
request,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION),
|
||||
reinterpret_cast<PVOID*>(¬ify),
|
||||
nullptr
|
||||
)))
|
||||
{
|
||||
//
|
||||
// Assign values to output buffer
|
||||
//
|
||||
notify->Size = sizeof(DS4_REQUEST_NOTIFICATION);
|
||||
notify->SerialNo = this->_SerialNo;
|
||||
notify->Report = *static_cast<PDS4_OUTPUT_REPORT>(clientBuffer);
|
||||
|
||||
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
|
||||
notify,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION)
|
||||
);
|
||||
|
||||
WdfRequestCompleteWithInformation(request, status, notify->Size);
|
||||
}
|
||||
|
||||
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
|
||||
|
||||
//
|
||||
// If no more buffer to process, exit loop and await next callback
|
||||
//
|
||||
if (DMF_BufferQueue_Count(this->_UsbInterruptOutBufferQueue) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TraceVerbose(TRACE_USBPDO, "%!FUNC! Exit");
|
||||
}
|
||||
|
||||
VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
|
||||
_In_ WDFTIMER Timer
|
||||
)
|
||||
@@ -1202,7 +1297,7 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
|
||||
|
||||
WDFREQUEST usbRequest;
|
||||
|
||||
TraceDbg(TRACE_DS4, "%!FUNC! Entry");
|
||||
FuncEntry(TRACE_DS4);
|
||||
|
||||
// Get pending USB request
|
||||
const auto status = WdfIoQueueRetrieveNextRequest(ctx->_PendingUsbInRequests, &usbRequest);
|
||||
@@ -1231,5 +1326,5 @@ VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
|
||||
WdfRequestComplete(usbRequest, status);
|
||||
}
|
||||
|
||||
TraceDbg(TRACE_DS4, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceVerbose(TRACE_DS4, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,10 @@ namespace ViGEm::Bus::Targets
|
||||
static VOID ReverseByteArray(PUCHAR Array, INT Length);
|
||||
|
||||
static VOID GenerateRandomMacAddress(PMAC_ADDRESS Address);
|
||||
|
||||
|
||||
protected:
|
||||
void ProcessPendingNotification(WDFQUEUE Queue) override;
|
||||
private:
|
||||
static PCWSTR _deviceDescription;
|
||||
|
||||
static const int HID_REQUEST_GET_REPORT = 0x01;
|
||||
|
||||
@@ -87,7 +87,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfPdoInitAssignDeviceID failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -98,7 +98,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
status = RtlUnicodeStringPrintf(&buffer, L"%02d", this->_SerialNo);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"RtlUnicodeStringPrintf failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -109,7 +109,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfPdoInitAssignInstanceID failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -120,7 +120,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
status = WdfPdoInitAddDeviceText(DeviceInit, &deviceDescription, &deviceLocation, 0x409);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfPdoInitAddDeviceText failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -156,14 +156,14 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &this->_PdoDevice);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfDeviceCreate failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
"Created PDO 0x%p",
|
||||
this->_PdoDevice);
|
||||
@@ -179,7 +179,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfDeviceCreateDeviceInterface failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -200,7 +200,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"Couldn't initialize additional contexts: %!STATUS!",
|
||||
status);
|
||||
@@ -210,7 +210,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Create Queues & Locks
|
||||
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = this->_PdoDevice;
|
||||
|
||||
@@ -225,7 +225,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfIoQueueCreate (PendingUsbInRequests) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -246,13 +246,27 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfIoQueueCreate (PendingNotificationRequests) failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfIoQueueReadyNotify(
|
||||
this->_PendingNotificationRequests,
|
||||
EvtWdfIoPendingNotificationQueueState,
|
||||
this
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfIoQueueReadyNotify (PendingNotificationRequests) failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Default I/O queue setup
|
||||
@@ -272,7 +286,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfIoQueueCreate (Default) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -314,7 +328,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtDeviceContextCleanup(
|
||||
IN WDFOBJECT Device
|
||||
)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Entry");
|
||||
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Entry");
|
||||
|
||||
const auto ctx = EmulationTargetPdoGetContext(Device);
|
||||
|
||||
@@ -351,13 +365,13 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtDeviceContextCleanup(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// PDO device object getting disposed, free context object
|
||||
//
|
||||
delete ctx->Target;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_BUSPDO, "%!FUNC! Exit");
|
||||
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit");
|
||||
}
|
||||
|
||||
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::SubmitReport(PVOID NewReport)
|
||||
@@ -412,21 +426,21 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFREQUEST
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"KeWaitForSingleObject failed with status %!STATUS!",
|
||||
status
|
||||
TRACE_BUSPDO,
|
||||
"KeWaitForSingleObject failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status = WdfRequestForwardToIoQueue(Request, this->_WaitDeviceReadyRequests);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_BUSPDO,
|
||||
"WdfRequestForwardToIoQueue failed with status %!STATUS!",
|
||||
status
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfRequestForwardToIoQueue failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
|
||||
return status;
|
||||
@@ -435,23 +449,23 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFREQUEST
|
||||
OBJECT_ATTRIBUTES threadOb;
|
||||
|
||||
InitializeObjectAttributes(&threadOb, NULL,
|
||||
OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
|
||||
status = PsCreateSystemThread(&this->_WaitDeviceReadyCompletionWorkerThreadHandle,
|
||||
static_cast<ACCESS_MASK>(0L),
|
||||
&threadOb,
|
||||
nullptr,
|
||||
nullptr,
|
||||
WaitDeviceReadyCompletionWorkerRoutine,
|
||||
this
|
||||
static_cast<ACCESS_MASK>(0L),
|
||||
&threadOb,
|
||||
nullptr,
|
||||
nullptr,
|
||||
WaitDeviceReadyCompletionWorkerRoutine,
|
||||
this
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_BUSPDO,
|
||||
"PsCreateSystemThread failed with status %!STATUS!",
|
||||
status
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"PsCreateSystemThread failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
@@ -463,7 +477,9 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoPrepare(WDFDEVICE ParentDevice
|
||||
NTSTATUS status;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
WDF_IO_QUEUE_CONFIG plugInQueueConfig;
|
||||
|
||||
DMF_MODULE_ATTRIBUTES moduleAttributes;
|
||||
DMF_CONFIG_BufferQueue dmfBufferCfg;
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = ParentDevice;
|
||||
|
||||
@@ -478,12 +494,47 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoPrepare(WDFDEVICE ParentDevice
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"WdfIoQueueCreate (PendingPlugInRequests) failed with status %!STATUS!",
|
||||
status);
|
||||
}
|
||||
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = ParentDevice;
|
||||
|
||||
DMF_CONFIG_BufferQueue_AND_ATTRIBUTES_INIT(
|
||||
&dmfBufferCfg,
|
||||
&moduleAttributes
|
||||
);
|
||||
|
||||
// Don't auto-grow; start dropping packets on overrun
|
||||
dmfBufferCfg.SourceSettings.EnableLookAside = FALSE;
|
||||
// Maximum number of buffers to be filled and kept queued
|
||||
dmfBufferCfg.SourceSettings.BufferCount = MAX_OUT_BUFFER_QUEUE_COUNT;
|
||||
// Maximum byte count per buffer
|
||||
dmfBufferCfg.SourceSettings.BufferSize = MAX_OUT_BUFFER_QUEUE_SIZE;
|
||||
// Field to store real buffer content length
|
||||
dmfBufferCfg.SourceSettings.BufferContextSize = sizeof(size_t);
|
||||
// "Expensive" memory ;)
|
||||
dmfBufferCfg.SourceSettings.PoolType = NonPagedPoolNx;
|
||||
|
||||
status = DMF_BufferQueue_Create(
|
||||
ParentDevice,
|
||||
&moduleAttributes,
|
||||
&attributes,
|
||||
&this->_UsbInterruptOutBufferQueue
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceError(
|
||||
TRACE_BUSPDO,
|
||||
"DMF_BufferQueue_Create failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -564,8 +615,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
|
||||
timeout.QuadPart = WDF_REL_TIMEOUT_IN_SEC(1);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_BUSPDO,
|
||||
"Waiting for 1 second to complete PDO boot..."
|
||||
TRACE_BUSPDO,
|
||||
"Waiting for 1 second to complete PDO boot..."
|
||||
);
|
||||
|
||||
NTSTATUS status = KeWaitForSingleObject(
|
||||
@@ -584,8 +635,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
|
||||
if (!NT_SUCCESS(WdfIoQueueRetrieveNextRequest(ctx->_WaitDeviceReadyRequests, &waitRequest)))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"No pending device wait request available"
|
||||
TRACE_BUSPDO,
|
||||
"No pending device wait request available"
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -593,8 +644,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
|
||||
if (status == STATUS_TIMEOUT)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"Device wait request timed out, completing with error"
|
||||
TRACE_BUSPDO,
|
||||
"Device wait request timed out, completing with error"
|
||||
);
|
||||
|
||||
//
|
||||
@@ -607,8 +658,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_BUSPDO,
|
||||
"Device wait request completed successfully"
|
||||
TRACE_BUSPDO,
|
||||
"Device wait request completed successfully"
|
||||
);
|
||||
|
||||
//
|
||||
@@ -617,8 +668,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::WaitDeviceReadyCompletionWorkerRoutin
|
||||
WdfRequestComplete(waitRequest, STATUS_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (FALSE);
|
||||
} while (FALSE);
|
||||
|
||||
ZwClose(ctx->_WaitDeviceReadyCompletionWorkerThreadHandle);
|
||||
ctx->_WaitDeviceReadyCompletionWorkerThreadHandle = nullptr;
|
||||
@@ -631,7 +681,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::DumpAsHex(PCSTR Prefix, PVOID Buffer,
|
||||
#ifdef DBG
|
||||
|
||||
size_t dumpBufferLength = ((BufferLength * sizeof(CHAR)) * 2) + 1;
|
||||
PSTR dumpBuffer = static_cast<PSTR>(ExAllocatePoolWithTag(
|
||||
PSTR dumpBuffer = static_cast<PSTR>(ExAllocatePoolZero(
|
||||
NonPagedPoolNx,
|
||||
dumpBufferLength,
|
||||
'1234'
|
||||
@@ -646,7 +696,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::DumpAsHex(PCSTR Prefix, PVOID Buffer,
|
||||
sprintf(&dumpBuffer[i * 2], "%02X", static_cast<PUCHAR>(Buffer)[i]);
|
||||
}
|
||||
|
||||
TraceDbg(TRACE_BUSPDO,
|
||||
TraceVerbose(TRACE_BUSPDO,
|
||||
"%s - Buffer length: %04d, buffer content: %s\n",
|
||||
Prefix,
|
||||
BufferLength,
|
||||
@@ -698,14 +748,14 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbGetConfigurationDescriptorType
|
||||
|
||||
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::UsbSelectConfiguration(PURB Urb)
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: TotalLength %d",
|
||||
Urb->UrbHeader.Length);
|
||||
|
||||
if (Urb->UrbHeader.Length == sizeof(struct _URB_SELECT_CONFIGURATION))
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: NULL ConfigurationDescriptor");
|
||||
return STATUS_SUCCESS;
|
||||
@@ -782,7 +832,7 @@ BOOLEAN ViGEm::Bus::Core::EmulationTargetPDO::EvtChildListIdentificationDescript
|
||||
|
||||
|
||||
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE ParentDevice, ULONG SerialNo,
|
||||
WDFREQUEST Request)
|
||||
WDFREQUEST Request)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PDO_IDENTIFICATION_DESCRIPTION description;
|
||||
@@ -790,13 +840,13 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
|
||||
WDF_CHILD_RETRIEVE_INFO childInfo;
|
||||
WDFDEVICE childDevice;
|
||||
|
||||
TraceDbg(TRACE_BUSPDO, "%!FUNC! Entry");
|
||||
|
||||
FuncEntry(TRACE_BUSPDO);
|
||||
|
||||
const WDFCHILDLIST list = WdfFdoGetDefaultChildList(ParentDevice);
|
||||
|
||||
WDF_CHILD_LIST_ITERATOR_INIT(
|
||||
&iterator,
|
||||
WdfRetrievePendingChildren // might not be online yet
|
||||
WdfRetrieveAddedChildren // might not be online yet
|
||||
);
|
||||
WdfChildListBeginIteration(
|
||||
list,
|
||||
@@ -818,6 +868,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
|
||||
sizeof(description)
|
||||
);
|
||||
|
||||
// ReSharper disable once CppAssignedValueIsNeverUsed
|
||||
description.SerialNo = SerialNo;
|
||||
|
||||
status = WdfChildListRetrieveNextDevice(
|
||||
@@ -839,8 +890,8 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueueWaitDeviceReady(WDFDEVICE
|
||||
&iterator
|
||||
);
|
||||
|
||||
TraceDbg(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
|
||||
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -850,7 +901,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EvtDevicePrepareHardware(
|
||||
_In_ WDFCMRESLIST ResourcesTranslated
|
||||
)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_BUSPDO, "%!FUNC! Entry");
|
||||
FuncEntry(TRACE_BUSPDO);
|
||||
|
||||
UNREFERENCED_PARAMETER(ResourcesRaw);
|
||||
UNREFERENCED_PARAMETER(ResourcesTranslated);
|
||||
@@ -882,7 +933,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
PURB urb;
|
||||
PIO_STACK_LOCATION irpStack;
|
||||
|
||||
TraceDbg(TRACE_BUSPDO, "%!FUNC! Entry");
|
||||
FuncEntry(TRACE_BUSPDO);
|
||||
|
||||
// No help from the framework available from here on
|
||||
irp = WdfRequestWdmGetIrp(Request);
|
||||
@@ -892,7 +943,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
{
|
||||
case IOCTL_INTERNAL_USB_SUBMIT_URB:
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> IOCTL_INTERNAL_USB_SUBMIT_URB");
|
||||
|
||||
@@ -902,7 +953,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
{
|
||||
case URB_FUNCTION_CONTROL_TRANSFER:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_CONTROL_TRANSFER");
|
||||
|
||||
@@ -912,7 +963,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_CONTROL_TRANSFER_EX:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_CONTROL_TRANSFER_EX");
|
||||
|
||||
@@ -922,7 +973,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER");
|
||||
|
||||
@@ -932,7 +983,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_SELECT_CONFIGURATION:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_SELECT_CONFIGURATION");
|
||||
|
||||
@@ -942,7 +993,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_SELECT_INTERFACE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_SELECT_INTERFACE");
|
||||
|
||||
@@ -952,7 +1003,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE");
|
||||
|
||||
@@ -960,7 +1011,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
{
|
||||
case USB_DEVICE_DESCRIPTOR_TYPE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> >> USB_DEVICE_DESCRIPTOR_TYPE");
|
||||
|
||||
@@ -971,7 +1022,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> >> USB_CONFIGURATION_DESCRIPTOR_TYPE");
|
||||
|
||||
@@ -981,7 +1032,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case USB_STRING_DESCRIPTOR_TYPE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> >> USB_STRING_DESCRIPTOR_TYPE");
|
||||
|
||||
@@ -991,14 +1042,14 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
default:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> >> Unknown descriptor type");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
"<< <<");
|
||||
|
||||
@@ -1006,7 +1057,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_GET_STATUS_FROM_DEVICE");
|
||||
|
||||
@@ -1017,7 +1068,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_ABORT_PIPE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_ABORT_PIPE");
|
||||
|
||||
@@ -1027,7 +1078,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_CLASS_INTERFACE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_CLASS_INTERFACE");
|
||||
|
||||
@@ -1037,7 +1088,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE");
|
||||
|
||||
@@ -1047,7 +1098,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
default:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> >> Unknown function: 0x%X",
|
||||
urb->UrbHeader.Function);
|
||||
@@ -1055,7 +1106,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
break;
|
||||
}
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
"<<");
|
||||
|
||||
@@ -1063,7 +1114,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> IOCTL_INTERNAL_USB_GET_PORT_STATUS");
|
||||
|
||||
@@ -1076,7 +1127,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case IOCTL_INTERNAL_USB_RESET_PORT:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> IOCTL_INTERNAL_USB_RESET_PORT");
|
||||
|
||||
@@ -1087,7 +1138,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
|
||||
|
||||
@@ -1099,7 +1150,7 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
|
||||
default:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSPDO,
|
||||
">> Unknown I/O control code 0x%X",
|
||||
IoControlCode);
|
||||
@@ -1112,5 +1163,23 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtIoInternalDeviceControl(
|
||||
WdfRequestComplete(Request, status);
|
||||
}
|
||||
|
||||
TraceDbg(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceVerbose(TRACE_BUSPDO, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
}
|
||||
|
||||
void ViGEm::Bus::Core::EmulationTargetPDO::EvtWdfIoPendingNotificationQueueState(
|
||||
WDFQUEUE Queue,
|
||||
WDFCONTEXT Context
|
||||
)
|
||||
{
|
||||
const auto pThis = static_cast<EmulationTargetPDO*>(Context);
|
||||
|
||||
//
|
||||
// No buffer available to answer the request with, leave queued
|
||||
//
|
||||
if (DMF_BufferQueue_Count(pThis->_UsbInterruptOutBufferQueue) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pThis->ProcessPendingNotification(Queue);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#pragma warning(disable:5040)
|
||||
#include <DmfModules.Library.h>
|
||||
#pragma warning(default:5040)
|
||||
#include <ntddk.h>
|
||||
#include <wdf.h>
|
||||
#include <ntintsafe.h>
|
||||
@@ -43,7 +46,6 @@
|
||||
#include <usbbusif.h>
|
||||
|
||||
#include <ViGEm/Common.h>
|
||||
#include <initguid.h>
|
||||
|
||||
//
|
||||
// Some insane macro-magic =3
|
||||
@@ -144,6 +146,10 @@ namespace ViGEm::Bus::Core
|
||||
|
||||
static const int MAX_INSTANCE_ID_LEN = 80;
|
||||
|
||||
static const size_t MAX_OUT_BUFFER_QUEUE_COUNT = 64;
|
||||
|
||||
static const size_t MAX_OUT_BUFFER_QUEUE_SIZE = 128;
|
||||
|
||||
static PCWSTR _deviceLocation;
|
||||
|
||||
static BOOLEAN USB_BUSIFFN UsbInterfaceIsDeviceHighSpeed(IN PVOID BusContext);
|
||||
@@ -170,8 +176,12 @@ namespace ViGEm::Bus::Core
|
||||
|
||||
static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl;
|
||||
|
||||
static EVT_WDF_IO_QUEUE_STATE EvtWdfIoPendingNotificationQueueState;
|
||||
|
||||
static VOID WaitDeviceReadyCompletionWorkerRoutine(IN PVOID StartContext);
|
||||
|
||||
static VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
|
||||
|
||||
virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0;
|
||||
|
||||
virtual NTSTATUS SelectConfiguration(PURB Urb) = 0;
|
||||
@@ -180,7 +190,7 @@ namespace ViGEm::Bus::Core
|
||||
|
||||
virtual NTSTATUS SubmitReportImpl(PVOID NewReport) = 0;
|
||||
|
||||
static VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
|
||||
virtual VOID ProcessPendingNotification(WDFQUEUE Queue) = 0;
|
||||
|
||||
//
|
||||
// PNP Capabilities may differ from device to device
|
||||
@@ -251,6 +261,11 @@ namespace ViGEm::Bus::Core
|
||||
// Signals the bus that PDO is ready to receive data
|
||||
//
|
||||
KEVENT _PdoBootNotificationEvent;
|
||||
|
||||
//
|
||||
// Queue for interrupt out requests delivered to user-land
|
||||
//
|
||||
DMFMODULE _UsbInterruptOutBufferQueue{};
|
||||
};
|
||||
|
||||
typedef struct _PDO_IDENTIFICATION_DESCRIPTION
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
|
||||
|
||||
#include "Driver.h"
|
||||
#include "queue.tmh"
|
||||
#include "trace.h"
|
||||
#include "Queue.tmh"
|
||||
|
||||
#include "EmulationTargetPDO.hpp"
|
||||
#include "XusbPdo.hpp"
|
||||
#include "Ds4Pdo.hpp"
|
||||
|
||||
|
||||
using ViGEm::Bus::Core::PDO_IDENTIFICATION_DESCRIPTION;
|
||||
using ViGEm::Bus::Core::EmulationTargetPDO;
|
||||
using ViGEm::Bus::Targets::EmulationTargetXUSB;
|
||||
@@ -74,7 +74,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
Device = WdfIoQueueGetDevice(Queue);
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "%!FUNC! Entry (device: 0x%p)", Device);
|
||||
TraceVerbose(TRACE_QUEUE, "%!FUNC! Entry (device: 0x%p)", Device);
|
||||
|
||||
switch (IoControlCode)
|
||||
{
|
||||
@@ -82,7 +82,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_VIGEM_CHECK_VERSION:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_CHECK_VERSION");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_CHECK_VERSION");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
@@ -99,7 +99,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
status = (pCheckVersion->Version == VIGEM_COMMON_VERSION) ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_QUEUE,
|
||||
"Requested version: 0x%04X, compiled version: 0x%04X",
|
||||
pCheckVersion->Version, VIGEM_COMMON_VERSION);
|
||||
@@ -112,7 +112,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_VIGEM_WAIT_DEVICE_READY:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_WAIT_DEVICE_READY");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_WAIT_DEVICE_READY");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
@@ -130,7 +130,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
// This request only supports a single PDO at a time
|
||||
if (pWaitDeviceReady->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
@@ -154,7 +154,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_VIGEM_PLUGIN_TARGET:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_PLUGIN_TARGET");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_PLUGIN_TARGET");
|
||||
|
||||
status = Bus_PlugInDevice(Device, Request, FALSE, &length);
|
||||
|
||||
@@ -166,7 +166,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_VIGEM_UNPLUG_TARGET:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_UNPLUG_TARGET");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_VIGEM_UNPLUG_TARGET");
|
||||
|
||||
status = Bus_UnPlugDevice(Device, Request, FALSE, &length);
|
||||
|
||||
@@ -178,7 +178,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_XUSB_SUBMIT_REPORT:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_SUBMIT_REPORT");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_SUBMIT_REPORT");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
@@ -189,7 +189,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -201,7 +201,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
// This request only supports a single PDO at a time
|
||||
if (xusbSubmit->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
@@ -223,12 +223,12 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_XUSB_REQUEST_NOTIFICATION:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_REQUEST_NOTIFICATION");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_REQUEST_NOTIFICATION");
|
||||
|
||||
// Don't accept the request if the output buffer can't hold the results
|
||||
if (OutputBufferLength < sizeof(XUSB_REQUEST_NOTIFICATION))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(XUSB_REQUEST_NOTIFICATION)));
|
||||
@@ -244,7 +244,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -256,7 +256,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
// This request only supports a single PDO at a time
|
||||
if (xusbNotify->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
@@ -282,7 +282,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_DS4_SUBMIT_REPORT:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_DS4_SUBMIT_REPORT");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_DS4_SUBMIT_REPORT");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
@@ -293,7 +293,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -305,7 +305,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
//
|
||||
if (length < sizeof(DS4_SUBMIT_REPORT) || length > sizeof(DS4_SUBMIT_REPORT_EX))
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_QUEUE,
|
||||
"Unexpected buffer size: %d",
|
||||
static_cast<ULONG>(length)
|
||||
@@ -320,7 +320,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
//
|
||||
if (length != ds4Submit->Size)
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_QUEUE,
|
||||
"Invalid buffer size: %d",
|
||||
ds4Submit->Size
|
||||
@@ -335,7 +335,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
//
|
||||
if (ds4Submit->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
@@ -356,12 +356,12 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_DS4_REQUEST_NOTIFICATION:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_DS4_REQUEST_NOTIFICATION");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_DS4_REQUEST_NOTIFICATION");
|
||||
|
||||
// Don't accept the request if the output buffer can't hold the results
|
||||
if (OutputBufferLength < sizeof(DS4_REQUEST_NOTIFICATION))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(DS4_REQUEST_NOTIFICATION)));
|
||||
@@ -377,7 +377,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -389,7 +389,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
// This request only supports a single PDO at a time
|
||||
if (ds4Notify->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
@@ -415,7 +415,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
|
||||
case IOCTL_XUSB_GET_USER_INDEX:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_GET_USER_INDEX");
|
||||
TraceVerbose(TRACE_QUEUE, "IOCTL_XUSB_GET_USER_INDEX");
|
||||
|
||||
// Don't accept the request if the output buffer can't hold the results
|
||||
if (OutputBufferLength < sizeof(XUSB_GET_USER_INDEX))
|
||||
@@ -472,7 +472,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
WdfRequestCompleteWithInformation(Request, status, length);
|
||||
}
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceVerbose(TRACE_QUEUE, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
}
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
@@ -35,7 +35,7 @@ BEGIN
|
||||
VALUE "FileDescription", "Virtual Gamepad Emulation Framework Bus Driver"
|
||||
VALUE "FileVersion", "1.16.200.0"
|
||||
VALUE "InternalName", "Virtual Gamepad Emulation Framework Bus Driver"
|
||||
VALUE "LegalCopyright", "(C) 2016-2019 Nefarius Software Solutions e.U."
|
||||
VALUE "LegalCopyright", "(C) 2016-2020 Nefarius Software Solutions e.U."
|
||||
VALUE "OriginalFilename", "ViGEmBus.sys"
|
||||
VALUE "ProductName", "Virtual Gamepad Emulation Framework Bus Driver"
|
||||
VALUE "ProductVersion", "1.16.200.0"
|
||||
|
||||
@@ -17,177 +17,26 @@
|
||||
<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>{040101B0-EE5C-4EF1-99EE-9F81C795C001}</ProjectGuid>
|
||||
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<RootNamespace>ViGEmBus</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' == '' ">*</AppVeyorBuildVersion>
|
||||
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' != '' ">$(APPVEYOR_BUILD_VERSION)</AppVeyorBuildVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<TargetVersion>
|
||||
</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
|
||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<TargetVersion>
|
||||
</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
|
||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||
<SignMode>Off</SignMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<TargetVersion>
|
||||
</TargetVersion>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
|
||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<TargetVersion>
|
||||
</TargetVersion>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
|
||||
<KMDF_VERSION_MINOR>9</KMDF_VERSION_MINOR>
|
||||
<ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
|
||||
<SignMode>Off</SignMode>
|
||||
</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|Win32'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Inf>
|
||||
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Inf>
|
||||
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Inf>
|
||||
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Inf>
|
||||
<TimeStamp>$(AppVeyorBuildVersion)</TimeStamp>
|
||||
</Inf>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(DDK_LIB_PATH)ntstrsafe.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
<ClCompile>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<ClCompile>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppScanConfigurationData>trace.h</WppScanConfigurationData>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="ViGEmBus.inf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\sdk\include\ViGEm\km\BusShared.h" />
|
||||
<ClInclude Include="Driver.h" />
|
||||
@@ -211,6 +60,258 @@
|
||||
<ClCompile Include="Queue.cpp" />
|
||||
<ClCompile Include="XusbPdo.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{040101B0-EE5C-4EF1-99EE-9F81C795C001}</ProjectGuid>
|
||||
<TemplateGuid>{8c0e3d8b-df43-455b-815a-4a0e72973bc6}</TemplateGuid>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
|
||||
<RootNamespace>ViGEmBus</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' == '' ">*</AppVeyorBuildVersion>
|
||||
<AppVeyorBuildVersion Condition=" '$(APPVEYOR_BUILD_VERSION)' != '' ">$(APPVEYOR_BUILD_VERSION)</AppVeyorBuildVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<SignMode>Off</SignMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<SignMode>Off</SignMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||
<ConfigurationType>Driver</ConfigurationType>
|
||||
<DriverType>KMDF</DriverType>
|
||||
<DriverTargetPlatform>Universal</DriverTargetPlatform>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<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 Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(IncludePath);$(KMDF_INC_PATH)$(KMDF_VER_PATH)</IncludePath>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
<PreprocessorDefinitions>_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\..\DMF\DMF\Modules.Library;..\..\DMF\DMF\Framework;$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\..\DMF\Debug\Win32\lib\DmfK\DmfK.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
<PreprocessorDefinitions>_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\..\DMF\DMF\Modules.Library;..\..\DMF\DMF\Framework;$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\..\DMF\Release\Win32\lib\DmfK\DmfK.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Inf>
|
||||
<TimeStamp>1.0.0.0</TimeStamp>
|
||||
</Inf>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
<PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\..\DMF\DMF\Modules.Library;..\..\DMF\DMF\Framework;$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\..\DMF\Debug\x64\lib\DmfK\DmfK.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
<PreprocessorDefinitions>_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>..\..\DMF\DMF\Modules.Library;..\..\DMF\DMF\Framework;$(SolutionDir)include;$(SolutionDir)sdk\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\..\DMF\Release\x64\lib\DmfK\DmfK.lib;$(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies);ntstrsafe.lib;usbdex.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<Inf>
|
||||
<TimeStamp>1.0.0.0</TimeStamp>
|
||||
</Inf>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WppEnabled>true</WppEnabled>
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
|
||||
<WppKernelMode>true</WppKernelMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);ntstrsafe.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
206
sys/XusbPdo.cpp
206
sys/XusbPdo.cpp
@@ -32,14 +32,17 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "Driver.h"
|
||||
#include "XusbPdo.hpp"
|
||||
#include "trace.h"
|
||||
#include "XusbPdo.tmh"
|
||||
#define NTSTRSAFE_LIB
|
||||
#include <ntstrsafe.h>
|
||||
#include "Driver.h"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <usbbusif.h>
|
||||
|
||||
#include <ViGEm/km/BusShared.h>
|
||||
|
||||
PCWSTR ViGEm::Bus::Targets::EmulationTargetXUSB::_deviceDescription = L"Virtual Xbox 360 Controller";
|
||||
|
||||
@@ -83,7 +86,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = RtlUnicodeStringInit(DeviceDescription, _deviceDescription);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"RtlUnicodeStringInit failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -98,7 +101,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = WdfPdoInitAddHardwareID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfPdoInitAddHardwareID failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -112,7 +115,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfPdoInitAddCompatibleID #1 failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -124,7 +127,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfPdoInitAddCompatibleID #2 failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -136,7 +139,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfPdoInitAddCompatibleID #3 failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -148,7 +151,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
status = WdfPdoInitAddCompatibleID(DeviceInit, &buffer);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfPdoInitAddCompatibleID #4 failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -192,7 +195,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareHardware()
|
||||
status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfDeviceAddQueryInterface failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -210,7 +213,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
|
||||
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
|
||||
attributes.ParentObject = this->_PdoDevice;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_XUSB, "Initializing XUSB context...");
|
||||
TraceVerbose(TRACE_XUSB, "Initializing XUSB context...");
|
||||
|
||||
RtlZeroMemory(this->_Rumble, ARRAYSIZE(this->_Rumble));
|
||||
|
||||
@@ -236,7 +239,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfMemoryCreate failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -279,7 +282,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoInitContext()
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_XUSB,
|
||||
"WdfIoQueueCreate (HoldingUsbInRequests) failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -463,7 +466,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
|
||||
|
||||
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectConfiguration.Interface;
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_XUSB,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
(int)pInfo->Length,
|
||||
@@ -495,7 +498,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
|
||||
|
||||
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_XUSB,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
(int)pInfo->Length,
|
||||
@@ -543,7 +546,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
|
||||
|
||||
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_XUSB,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
(int)pInfo->Length,
|
||||
@@ -567,7 +570,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SelectConfiguration(PURB Urb)
|
||||
|
||||
pInfo = (PUSBD_INTERFACE_INFORMATION)((PCHAR)pInfo + pInfo->Length);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_XUSB,
|
||||
">> >> >> URB_FUNCTION_SELECT_CONFIGURATION: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
(int)pInfo->Length,
|
||||
@@ -606,7 +609,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbSelectInterface(PURB Urb)
|
||||
{
|
||||
PUSBD_INTERFACE_INFORMATION pInfo = &Urb->UrbSelectInterface.Interface;
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_INTERFACE: Length %d, Interface %d, Alternate %d, Pipes %d",
|
||||
(int)pInfo->Length,
|
||||
@@ -614,7 +617,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbSelectInterface(PURB Urb)
|
||||
(int)pInfo->AlternateSetting,
|
||||
pInfo->NumberOfPipes);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_SELECT_INTERFACE: Class %d, SubClass %d, Protocol %d",
|
||||
(int)pInfo->Class,
|
||||
@@ -697,13 +700,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbGetStringDescriptorType(PU
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request)
|
||||
{
|
||||
NTSTATUS status;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
WDFREQUEST notifyRequest;
|
||||
|
||||
// Data coming FROM us TO higher driver
|
||||
if (pTransfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN)
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> Incoming request, queuing...");
|
||||
|
||||
@@ -802,18 +805,20 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
}
|
||||
|
||||
// Data coming FROM the higher driver TO us
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
">> >> >> URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Handle %p, Flags %X, Length %d",
|
||||
pTransfer->PipeHandle,
|
||||
pTransfer->TransferFlags,
|
||||
pTransfer->TransferBufferLength);
|
||||
|
||||
#pragma region Cache values
|
||||
|
||||
if (pTransfer->TransferBufferLength == XUSB_LEDSET_SIZE) // Led
|
||||
{
|
||||
auto Buffer = static_cast<PUCHAR>(pTransfer->TransferBuffer);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"-- LED Buffer: %02X %02X %02X",
|
||||
Buffer[0], Buffer[1], Buffer[2]);
|
||||
@@ -826,16 +831,16 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
if (Buffer[2] == 0x04)this->_LedNumber = 2;
|
||||
if (Buffer[2] == 0x05)this->_LedNumber = 3;
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"-- LED Number: %d",
|
||||
this->_LedNumber);
|
||||
|
||||
//
|
||||
// Notify client library that PDO is ready
|
||||
//
|
||||
KeSetEvent(&this->_PdoBootNotificationEvent, 0, FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Notify client library that PDO is ready
|
||||
//
|
||||
KeSetEvent(&this->_PdoBootNotificationEvent, 0, FALSE);
|
||||
}
|
||||
|
||||
// Extract rumble (vibration) information
|
||||
@@ -843,7 +848,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
{
|
||||
auto Buffer = static_cast<PUCHAR>(pTransfer->TransferBuffer);
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_USBPDO,
|
||||
"-- Rumble Buffer: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
Buffer[0],
|
||||
@@ -858,12 +863,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
RtlCopyBytes(this->_Rumble, Buffer, pTransfer->TransferBufferLength);
|
||||
}
|
||||
|
||||
// Notify user-mode process that new data is available
|
||||
status = WdfIoQueueRetrieveNextRequest(this->_PendingNotificationRequests, ¬ifyRequest);
|
||||
#pragma endregion
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
if (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(
|
||||
this->_PendingNotificationRequests,
|
||||
¬ifyRequest
|
||||
)))
|
||||
{
|
||||
PXUSB_REQUEST_NOTIFICATION notify = NULL;
|
||||
PXUSB_REQUEST_NOTIFICATION notify = nullptr;
|
||||
|
||||
status = WdfRequestRetrieveOutputBuffer(
|
||||
notifyRequest,
|
||||
@@ -881,11 +888,16 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
notify->LargeMotor = this->_Rumble[3];
|
||||
notify->SmallMotor = this->_Rumble[4];
|
||||
|
||||
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
|
||||
notify,
|
||||
sizeof(XUSB_REQUEST_NOTIFICATION)
|
||||
);
|
||||
|
||||
WdfRequestCompleteWithInformation(notifyRequest, status, notify->Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_USBPDO,
|
||||
"WdfRequestRetrieveOutputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -893,10 +905,26 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbBulkOrInterruptTransfer(_U
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_USBPDO,
|
||||
"!! WdfIoQueueRetrieveNextRequest failed with status %!STATUS!",
|
||||
status);
|
||||
PVOID clientBuffer, contextBuffer;
|
||||
|
||||
if (NT_SUCCESS(DMF_BufferQueue_Fetch(
|
||||
this->_UsbInterruptOutBufferQueue,
|
||||
&clientBuffer,
|
||||
&contextBuffer
|
||||
)) && pTransfer->TransferBufferLength <= MAX_OUT_BUFFER_QUEUE_SIZE)
|
||||
{
|
||||
RtlCopyMemory(
|
||||
clientBuffer,
|
||||
pTransfer->TransferBuffer,
|
||||
pTransfer->TransferBufferLength
|
||||
);
|
||||
|
||||
*static_cast<size_t*>(contextBuffer) = pTransfer->TransferBufferLength;
|
||||
|
||||
TraceVerbose(TRACE_USBPDO, "Queued %Iu bytes", pTransfer->TransferBufferLength);
|
||||
|
||||
DMF_BufferQueue_Enqueue(this->_UsbInterruptOutBufferQueue, clientBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -947,7 +975,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::UsbControlTransfer(PURB Urb)
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewReport)
|
||||
{
|
||||
TraceDbg(TRACE_BUSENUM, "%!FUNC! Entry");
|
||||
FuncEntry(TRACE_BUSENUM);
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
BOOLEAN changed;
|
||||
@@ -960,14 +988,14 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewRep
|
||||
// Don't waste pending IRP if input hasn't changed
|
||||
if (!changed)
|
||||
{
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"Input report hasn't changed since last update, aborting with %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
TraceDbg(
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"Received new report, processing");
|
||||
|
||||
@@ -995,7 +1023,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::SubmitReportImpl(PVOID NewRep
|
||||
// Complete pending request
|
||||
WdfRequestComplete(usbRequest, status);
|
||||
|
||||
TraceDbg(TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
TraceVerbose(TRACE_BUSENUM, "%!FUNC! Exit with status %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -1007,7 +1035,7 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::GetUserIndex(PULONG UserIndex
|
||||
|
||||
if (!UserIndex)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
|
||||
if (this->_LedNumber >= 0)
|
||||
{
|
||||
*UserIndex = static_cast<ULONG>(this->_LedNumber);
|
||||
@@ -1018,3 +1046,95 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::GetUserIndex(PULONG UserIndex
|
||||
// and need to fail this request with a distinct status.
|
||||
return STATUS_INVALID_DEVICE_OBJECT_PARAMETER;
|
||||
}
|
||||
|
||||
void ViGEm::Bus::Targets::EmulationTargetXUSB::ProcessPendingNotification(WDFQUEUE Queue)
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDFREQUEST request;
|
||||
PVOID clientBuffer, contextBuffer;
|
||||
size_t bufferLength;
|
||||
PXUSB_REQUEST_NOTIFICATION notify = nullptr;
|
||||
|
||||
FuncEntry(TRACE_BUSENUM);
|
||||
|
||||
//
|
||||
// Loop through and drain all queued requests until buffer is empty
|
||||
//
|
||||
while (NT_SUCCESS(WdfIoQueueRetrieveNextRequest(Queue, &request)))
|
||||
{
|
||||
status = DMF_BufferQueue_Dequeue(
|
||||
this->_UsbInterruptOutBufferQueue,
|
||||
&clientBuffer,
|
||||
&contextBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Shouldn't happen, but if so, error out
|
||||
//
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
//
|
||||
// Don't requeue request as we maya be out of order now
|
||||
//
|
||||
WdfRequestComplete(request, status);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Actual buffer length
|
||||
//
|
||||
bufferLength = *static_cast<size_t*>(contextBuffer);
|
||||
|
||||
//
|
||||
// Validate packet
|
||||
//
|
||||
if (bufferLength != XUSB_RUMBLE_SIZE && bufferLength != XUSB_LEDSET_SIZE)
|
||||
{
|
||||
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
|
||||
WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
|
||||
break; // await callback getting fired again
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(WdfRequestRetrieveOutputBuffer(
|
||||
request,
|
||||
sizeof(XUSB_REQUEST_NOTIFICATION),
|
||||
reinterpret_cast<PVOID*>(¬ify),
|
||||
nullptr
|
||||
)))
|
||||
{
|
||||
notify->Size = sizeof(XUSB_REQUEST_NOTIFICATION);
|
||||
notify->SerialNo = this->_SerialNo;
|
||||
notify->LedNumber = this->_LedNumber; // Report last cached value
|
||||
|
||||
if (bufferLength == XUSB_RUMBLE_SIZE)
|
||||
{
|
||||
notify->LargeMotor = static_cast<PUCHAR>(clientBuffer)[3];
|
||||
notify->SmallMotor = static_cast<PUCHAR>(clientBuffer)[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
notify->LargeMotor = this->_Rumble[3]; // Cached value
|
||||
notify->SmallMotor = this->_Rumble[4]; // Cached value
|
||||
}
|
||||
|
||||
DumpAsHex("!! XUSB_REQUEST_NOTIFICATION",
|
||||
notify,
|
||||
sizeof(XUSB_REQUEST_NOTIFICATION)
|
||||
);
|
||||
|
||||
WdfRequestCompleteWithInformation(request, status, notify->Size);
|
||||
}
|
||||
|
||||
DMF_BufferQueue_Reuse(this->_UsbInterruptOutBufferQueue, clientBuffer);
|
||||
|
||||
//
|
||||
// If no more buffer to process, exit loop and await next callback
|
||||
//
|
||||
if (DMF_BufferQueue_Count(this->_UsbInterruptOutBufferQueue) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TraceVerbose(TRACE_BUSENUM, "%!FUNC! Exit");
|
||||
}
|
||||
|
||||
@@ -96,7 +96,9 @@ namespace ViGEm::Bus::Targets
|
||||
NTSTATUS SubmitReportImpl(PVOID NewReport) override;
|
||||
|
||||
NTSTATUS GetUserIndex(PULONG UserIndex) const;
|
||||
|
||||
|
||||
protected:
|
||||
void ProcessPendingNotification(WDFQUEUE Queue) override;
|
||||
private:
|
||||
static PCWSTR _deviceDescription;
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
#include "Driver.h"
|
||||
#include "trace.h"
|
||||
#include "busenum.tmh"
|
||||
|
||||
#include "EmulationTargetPDO.hpp"
|
||||
@@ -81,7 +82,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!", status);
|
||||
return status;
|
||||
@@ -89,7 +90,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
|
||||
if ((sizeof(VIGEM_PLUGIN_TARGET) != plugIn->Size) || (length != plugIn->Size))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"sizeof(VIGEM_PLUGIN_TARGET) buffer size mismatch [%d != %d]",
|
||||
sizeof(VIGEM_PLUGIN_TARGET), plugIn->Size);
|
||||
@@ -98,7 +99,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
|
||||
if (plugIn->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"Serial no. 0 not allowed");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
@@ -109,7 +110,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
fileObject = WdfRequestGetFileObject(Request);
|
||||
if (fileObject == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p",
|
||||
Request);
|
||||
@@ -119,7 +120,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
pFileData = FileObjectGetData(fileObject);
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"FileObjectGetData failed to get context data for 0x%p",
|
||||
fileObject);
|
||||
@@ -196,7 +197,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -211,7 +212,7 @@ EXTERN_C NTSTATUS Bus_PlugInDevice(
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"The described PDO already exists (%!STATUS!)",
|
||||
status);
|
||||
@@ -260,7 +261,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -269,7 +270,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
|
||||
if ((sizeof(VIGEM_UNPLUG_TARGET) != unPlug->Size) || (length != unPlug->Size))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"sizeof(VIGEM_UNPLUG_TARGET) buffer size mismatch [%d != %d]",
|
||||
sizeof(VIGEM_UNPLUG_TARGET), unPlug->Size);
|
||||
@@ -282,7 +283,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
fileObject = WdfRequestGetFileObject(Request);
|
||||
if (fileObject == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfRequestGetFileObject failed to fetch WDFFILEOBJECT from request 0x%p",
|
||||
Request);
|
||||
@@ -292,14 +293,14 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
pFileData = FileObjectGetData(fileObject);
|
||||
if (pFileData == NULL)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"FileObjectGetData failed to get context data for 0x%p",
|
||||
fileObject);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"Starting child list traversal");
|
||||
|
||||
@@ -319,7 +320,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
// Error or no more children, end loop
|
||||
if (!NT_SUCCESS(status) || status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"WdfChildListRetrieveNextDevice returned with status %!STATUS!",
|
||||
status);
|
||||
@@ -329,7 +330,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
// If unable to retrieve device
|
||||
if (childInfo.Status != WdfChildListRetrieveDeviceSuccess)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"childInfo.Status = %d",
|
||||
childInfo.Status);
|
||||
@@ -339,7 +340,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
// Child isn't the one we looked for, skip
|
||||
if (!unplugAll && description.SerialNo != unPlug->SerialNo)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"Seeking serial mismatch: %d != %d",
|
||||
description.SerialNo,
|
||||
@@ -347,7 +348,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
continue;
|
||||
}
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"description.SessionId = %d, pFileData->SessionId = %d",
|
||||
description.SessionId,
|
||||
@@ -360,7 +361,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
status = WdfChildListUpdateChildDescriptionAsMissing(list, &description.Header);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TraceError(
|
||||
TRACE_BUSENUM,
|
||||
"WdfChildListUpdateChildDescriptionAsMissing failed with status %!STATUS!",
|
||||
status);
|
||||
@@ -370,7 +371,7 @@ EXTERN_C NTSTATUS Bus_UnPlugDevice(
|
||||
|
||||
WdfChildListEndIteration(list, &iterator);
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TraceVerbose(
|
||||
TRACE_BUSENUM,
|
||||
"Finished child list traversal");
|
||||
|
||||
|
||||
24
sys/trace.h
24
sys/trace.h
@@ -44,6 +44,7 @@
|
||||
ViGEmBusTraceGuid, (c5ce18fe,27bd,4049,b0b4,8a47cab1dcd9), \
|
||||
\
|
||||
WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
|
||||
WPP_DEFINE_BIT(DMF_TRACE) \
|
||||
WPP_DEFINE_BIT(TRACE_BUSENUM) \
|
||||
WPP_DEFINE_BIT(TRACE_BUSPDO) \
|
||||
WPP_DEFINE_BIT(TRACE_BYTEARRAY) \
|
||||
@@ -73,9 +74,28 @@
|
||||
// This comment block is scanned by the trace preprocessor to define our
|
||||
// Trace function.
|
||||
//
|
||||
// USEPREFIX and USESUFFIX strip all trailing whitespace, so we need to surround
|
||||
// FuncExit messages with brackets
|
||||
//
|
||||
// begin_wpp config
|
||||
// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
|
||||
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
|
||||
// FUNC TraceDbg{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
|
||||
// FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
|
||||
// FUNC FuncEntryArguments{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
|
||||
// FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
|
||||
// FUNC FuncExitVoid{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
|
||||
// FUNC TraceError{LEVEL=TRACE_LEVEL_ERROR}(FLAGS, MSG, ...);
|
||||
// FUNC TraceInformation{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS, MSG, ...);
|
||||
// FUNC TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS, MSG, ...);
|
||||
// FUNC FuncExitNoReturn{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS);
|
||||
// USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> Entry");
|
||||
// USEPREFIX(FuncEntryArguments, "%!STDPREFIX! [%!FUNC!] --> Entry <");
|
||||
// USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <-- Exit <");
|
||||
// USESUFFIX(FuncExit, ">");
|
||||
// USEPREFIX(FuncExitVoid, "%!STDPREFIX! [%!FUNC!] <-- Exit");
|
||||
// USEPREFIX(TraceError, "%!STDPREFIX! [%!FUNC!] ERROR:");
|
||||
// USEPREFIX(TraceEvents, "%!STDPREFIX! [%!FUNC!] ");
|
||||
// USEPREFIX(TraceInformation, "%!STDPREFIX! [%!FUNC!] ");
|
||||
// USEPREFIX(TraceVerbose, "%!STDPREFIX! [%!FUNC!] ");
|
||||
// USEPREFIX(FuncExitNoReturn, "%!STDPREFIX! [%!FUNC!] <--");
|
||||
// end_wpp
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user