mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-15 11:55:10 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d29d9415b2 | ||
|
|
3212981cc9 | ||
|
|
7ea12a8517 | ||
|
|
82ac30e49f | ||
|
|
d177f23476 | ||
|
|
13050b05e5 | ||
|
|
673881bc47 | ||
|
|
74ddd96d32 | ||
|
|
48622f6a58 | ||
|
|
0ca353b250 | ||
|
|
ddd7853810 | ||
|
|
51a697659b | ||
|
|
412ece18fc | ||
|
|
1d247d44d5 | ||
|
|
2011bfafd6 | ||
|
|
b434d7975d | ||
|
|
2d8017dbda | ||
|
|
6da3732968 | ||
|
|
f3ead543ab | ||
|
|
ad3995eeae | ||
|
|
78a7fd418a | ||
|
|
518f65b8c0 | ||
|
|
041d6935ff | ||
|
|
69ee95c79a | ||
|
|
b6e588116d | ||
|
|
c3bc8782f4 | ||
|
|
c600e1a423 | ||
|
|
6741a1f2fd | ||
|
|
ce61a246a6 | ||
|
|
e96a280bde | ||
|
|
5aa9ad1e02 | ||
|
|
d60a1e0c0f | ||
|
|
03a9beae41 |
@@ -9,23 +9,23 @@ AllowShortCaseLabelsOnASingleLine: 'false'
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: 'false'
|
||||
AllowShortLoopsOnASingleLine: 'false'
|
||||
AlwaysBreakAfterDefinitionReturnType: All
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: 'false'
|
||||
AlwaysBreakBeforeMultilineStrings: 'true'
|
||||
BinPackArguments: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Linux
|
||||
BreakBeforeTernaryOperators: 'false'
|
||||
BreakStringLiterals: 'true'
|
||||
ColumnLimit: '120'
|
||||
ContinuationIndentWidth: '8'
|
||||
ColumnLimit: '80'
|
||||
ContinuationIndentWidth: '4'
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: 'false'
|
||||
IndentCaseLabels: 'true'
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'false'
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'true'
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: '1'
|
||||
PointerAlignment: Right
|
||||
|
||||
73
.gitlab-ci.yml
Normal file
73
.gitlab-ci.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
image: debian
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- release
|
||||
- releasetag
|
||||
|
||||
build:
|
||||
stage: build
|
||||
before_script:
|
||||
- apt-get update && apt-get -qq install clang mingw-w64 git make zip > /dev/null
|
||||
script:
|
||||
- make
|
||||
artifacts:
|
||||
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
||||
paths:
|
||||
- build
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
test:
|
||||
allow_failure: true
|
||||
stage: test
|
||||
dependencies:
|
||||
- build
|
||||
before_script:
|
||||
- apt-get update && apt-get -qq install make wine unzip > /dev/null
|
||||
- dpkg --add-architecture i386 && apt-get update && apt-get -qq install wine32 > /dev/null
|
||||
script:
|
||||
- ls
|
||||
- make run-tests
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
release:
|
||||
stage: release
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
dependencies:
|
||||
- build
|
||||
before_script:
|
||||
- apt-get update && apt-get -qq install zip > /dev/null
|
||||
script:
|
||||
- mv build/bemanitools.zip ./bemanitools.zip
|
||||
- find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete
|
||||
- unzip bemanitools.zip
|
||||
- rm bemanitools.zip
|
||||
artifacts:
|
||||
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
||||
paths:
|
||||
- ./*
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
releasetag:
|
||||
stage: releasetag
|
||||
dependencies: []
|
||||
before_script:
|
||||
- apt-get update && apt-get -qq install curl > /dev/null
|
||||
script:
|
||||
- |
|
||||
curl --silent --show-error \
|
||||
--data "{\"tag_name\": \"${CI_COMMIT_TAG}\", \"name\": \"${CI_PROJECT_NAME}-${CI_COMMIT_TAG}\", \"description\": \"${CI_COMMIT_TAG_MESSAGE:-No release notes.}\"}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Private-Token: ${CI_PRIVATE_TOKEN}" \
|
||||
--request POST \
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/releases"
|
||||
only:
|
||||
- tags
|
||||
@@ -1,4 +1,13 @@
|
||||
# Release history
|
||||
## 5.28
|
||||
* Improve documentation in various places
|
||||
* Automatic code formatting in build pipeline
|
||||
* Bugfix: Recursive config.bat script
|
||||
* Enable automatic building on pushes to master
|
||||
* Bugfix: Stop SDVX hanging on thankyou for playing
|
||||
* sdvx2: Support for Vivid Wave using sdvxhook2
|
||||
* sdvxio-kfca: Driver for real sdvx cabinet IO hardware
|
||||
|
||||
## 5.27
|
||||
* Various documentation updates regarding development and how to contribute
|
||||
* KFCA emulation accuracy fixes
|
||||
|
||||
49
GNUmakefile
49
GNUmakefile
@@ -22,24 +22,58 @@ gitrev := $(shell git rev-parse HEAD)
|
||||
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev)
|
||||
cflags := -O2 -pipe -ffunction-sections -fdata-sections \
|
||||
-Wall -std=c99
|
||||
ldflags := -Wl,--gc-sections -static-libgcc
|
||||
cflags_release := -Werror
|
||||
ldflags := -Wl,--gc-sections -static-libgcc
|
||||
|
||||
#
|
||||
# The first target that GNU Make encounters becomes the default target.
|
||||
# Define our ultimate target (`all') here, and also some helpers
|
||||
#
|
||||
|
||||
all:
|
||||
all: build
|
||||
|
||||
.PHONY: \
|
||||
clean \
|
||||
code-format \
|
||||
print-building \
|
||||
print-release \
|
||||
run-tests \
|
||||
version
|
||||
|
||||
release: \
|
||||
print-release \
|
||||
clean \
|
||||
code-format \
|
||||
all \
|
||||
run-tests
|
||||
|
||||
build: \
|
||||
print-building \
|
||||
version
|
||||
|
||||
print-building:
|
||||
@echo "Build gitrev "$(gitrev)"..."
|
||||
|
||||
print-release:
|
||||
@echo "Starting release build..."
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up..."
|
||||
$(V)rm -rf $(BUILDDIR)
|
||||
|
||||
code-format:
|
||||
@echo "Applying clang-format..."
|
||||
# -style=file enables reading .clang-format
|
||||
@find src/ -iname *.h -o -iname *.c | xargs clang-format -i -style=file
|
||||
|
||||
run-tests:
|
||||
@echo "Running tests..."
|
||||
@./run-tests-wine.sh
|
||||
|
||||
# Generate a version file to identify the build
|
||||
version:
|
||||
@echo "$(gitrev)" > version
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
$(V)rm -rf $(BUILDDIR)
|
||||
|
||||
#
|
||||
# Pull in module definitions
|
||||
#
|
||||
@@ -71,6 +105,7 @@ define t_moddefs
|
||||
|
||||
cppflags_$3 += $(cppflags) -DBUILD_MODULE=$3
|
||||
cflags_$3 += $(cflags)
|
||||
release: cflags_$3 += $(cflags_release)
|
||||
ldflags_$3 += $(ldflags)
|
||||
srcdir_$3 ?= src/main/$3
|
||||
|
||||
|
||||
24
Module.mk
24
Module.mk
@@ -80,8 +80,10 @@ include src/main/aciotest/Module.mk
|
||||
include src/main/bio2emu/Module.mk
|
||||
include src/main/bsthook/Module.mk
|
||||
include src/main/bstio/Module.mk
|
||||
include src/main/camhook/Module.mk
|
||||
include src/main/cconfig/Module.mk
|
||||
include src/main/config/Module.mk
|
||||
include src/main/d3d9exhook/Module.mk
|
||||
include src/main/ddrhook/Module.mk
|
||||
include src/main/ddrio/Module.mk
|
||||
include src/main/ddrio-smx/Module.mk
|
||||
@@ -133,6 +135,7 @@ include src/main/p3ioemu/Module.mk
|
||||
include src/main/p4ioemu/Module.mk
|
||||
include src/main/pcbidgen/Module.mk
|
||||
include src/main/sdvxhook/Module.mk
|
||||
include src/main/sdvxhook2/Module.mk
|
||||
include src/main/sdvxio/Module.mk
|
||||
include src/main/sdvxio-kfca/Module.mk
|
||||
include src/main/security/Module.mk
|
||||
@@ -146,6 +149,7 @@ include src/test/iidxhook-util/Module.mk
|
||||
include src/test/security/Module.mk
|
||||
include src/test/test/Module.mk
|
||||
include src/test/util/Module.mk
|
||||
include src/test/iidxhook8/Module.mk
|
||||
|
||||
#
|
||||
# Distribution build rules
|
||||
@@ -355,7 +359,9 @@ $(zipdir)/iidx-25-to-26.zip: \
|
||||
build/bin/indep-64/vefxio.dll \
|
||||
dist/iidx/config.bat \
|
||||
dist/iidx/gamestart-25.bat \
|
||||
dist/iidx/gamestart-26.bat \
|
||||
dist/iidx/iidxhook-25.conf \
|
||||
dist/iidx/iidxhook-26.conf \
|
||||
dist/iidx/vefx.txt \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
@@ -415,6 +421,21 @@ $(zipdir)/sdvx.zip: \
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
$(zipdir)/sdvx5.zip: \
|
||||
build/bin/avs2_1700-64/launcher.exe \
|
||||
build/bin/avs2_1700-64/sdvxhook2.dll \
|
||||
build/bin/indep-64/config.exe \
|
||||
build/bin/indep-64/eamio.dll \
|
||||
build/bin/indep-64/geninput.dll \
|
||||
build/bin/indep-64/sdvxio.dll \
|
||||
build/bin/indep-64/sdvxio-kfca.dll \
|
||||
dist/sdvx5/config.bat \
|
||||
dist/sdvx5/gamestart.bat \
|
||||
dist/sdvx5/sdvxhook2.conf \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
$(zipdir)/ddr-12-to-16.zip: \
|
||||
build/bin/avs2_1508-32/launcher.exe \
|
||||
build/bin/avs2_1508-32/ddrhook.dll \
|
||||
@@ -451,6 +472,7 @@ $(zipdir)/bst.zip: \
|
||||
|
||||
$(zipdir)/doc.zip: \
|
||||
doc/iidxhook \
|
||||
doc/sdvxhook \
|
||||
doc/jbhook \
|
||||
doc/tools \
|
||||
| $(zipdir)/
|
||||
@@ -477,6 +499,7 @@ $(BUILDDIR)/tests.zip: \
|
||||
build/bin/indep-32/security-rp3-test.exe \
|
||||
build/bin/indep-32/security-util-test.exe \
|
||||
build/bin/indep-32/util-net-test.exe \
|
||||
build/bin/indep-64/iidxhook8-config-cam-test.exe \
|
||||
dist/test/run-tests.sh \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
@@ -499,6 +522,7 @@ $(BUILDDIR)/bemanitools.zip: \
|
||||
$(zipdir)/jb-08.zip \
|
||||
$(zipdir)/src.zip \
|
||||
$(zipdir)/sdvx.zip \
|
||||
$(zipdir)/sdvx5.zip \
|
||||
$(zipdir)/tools.zip \
|
||||
$(zipdir)/tools-x64.zip \
|
||||
CHANGELOG.md \
|
||||
|
||||
73
README.md
73
README.md
@@ -1,5 +1,7 @@
|
||||
# Bemanitools 5
|
||||
Version: 5.27</br>
|
||||
[](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
|
||||
|
||||
Version: 5.28</br>
|
||||
[Release history](CHANGELOG.md)
|
||||
|
||||
A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
|
||||
@@ -11,44 +13,45 @@ authentic gameplay experience, and easier support for a broader range of release
|
||||
|
||||
# List of supported games
|
||||
* BeatStream
|
||||
* BeatStream (bst.zip)
|
||||
* BeatStream アニムトライヴ (bst.zip)
|
||||
* BeatStream (bst.zip) using bsthook
|
||||
* BeatStream アニムトライヴ (bst.zip) using bsthook
|
||||
* Dance Dance Revolution
|
||||
* Dance Dance Revolution X2 (ddr-12-to-16.zip)
|
||||
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip)
|
||||
* Dance Dance Revolution 2013 (ddr-12-to-16.zip)
|
||||
* Dance Dance Revolution 2014 (ddr-12-to-16.zip)
|
||||
* Dance Dance Revolution A (ddr-12-to-16.zip)
|
||||
* Dance Dance Revolution X2 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution X3 vs. 2ndMIX (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution 2013 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution 2014 (ddr-12-to-16.zip) using ddrhook
|
||||
* Dance Dance Revolution A (ddr-12-to-16.zip) using ddrhook
|
||||
* Beatmania IIDX
|
||||
* Beatmania IIDX 9th Style (iidx-09-to-12.zip)
|
||||
* Beatmania IIDX 10th Style (iidx-09-to-12.zip)
|
||||
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip)
|
||||
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip)
|
||||
* Beatmania IIDX 13 DistorteD (iidx-13.zip)
|
||||
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip)
|
||||
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip)
|
||||
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip)
|
||||
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip)
|
||||
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip)
|
||||
* Beatmania IIDX 19 Lincle (iidx-19.zip)
|
||||
* Beatmania IIDX 20 Tricoro (iidx-20.zip)
|
||||
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip)
|
||||
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip)
|
||||
* Beatmania IIDX 23 copula (iidx-21-to-24.zip)
|
||||
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip)
|
||||
* Beatmania IIDX 25 CANNON BALLERS (iidx-25-to-26.zip)
|
||||
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip)
|
||||
* Beatmania IIDX 9th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 10th Style (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 11 IIDX RED (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 12 HAPPY SKY (iidx-09-to-12.zip) using [iidxhook1](doc/iidxhook/iidxhook1.md)
|
||||
* Beatmania IIDX 13 DistorteD (iidx-13.zip) using [iidxhook2](doc/iidxhook/iidxhook2.md)
|
||||
* Beatmania IIDX 14 GOLD (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 15 DJ TROOPERS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 16 EMPRESS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 17 SIRIUS (iidx-14-to-17.zip) using [iidxhook3](doc/iidxhook/iidxhook3.md)
|
||||
* Beatmania IIDX 18 Resort Anthem (iidx-18.zip) using [iidxhook4](doc/iidxhook/iidxhook4.md)
|
||||
* Beatmania IIDX 19 Lincle (iidx-19.zip) using [iidxhook5](doc/iidxhook/iidxhook5.md)
|
||||
* Beatmania IIDX 20 Tricoro (iidx-20.zip) using [iidxhook6](doc/iidxhook/iidxhook6.md)
|
||||
* Beatmania IIDX 21 SPADA (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 22 PENDUAL (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 23 copula (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 24 SINOBUZ (iidx-21-to-24.zip) using [iidxhook7](doc/iidxhook/iidxhook7.md)
|
||||
* Beatmania IIDX 25 CANNON BALLERS (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||
* jubeat
|
||||
* jubeat (experimental/buggy) (jb-01.zip)
|
||||
* jubeat saucer (fulfill) (jb-05-to-07.zip)
|
||||
* jubeat prop (jb-05-to-07.zip)
|
||||
* jubeat Qubell (jb-05-to-07.zip)
|
||||
* jubeat clan (jb-08.zip)
|
||||
* jubeat (experimental/buggy) (jb-01.zip) using [jbhook1](doc/jbhook1/jbhook1.md)
|
||||
* jubeat saucer (fulfill) (jb-05-to-07.zip) using jbhook
|
||||
* jubeat prop (jb-05-to-07.zip) using jbhook
|
||||
* jubeat Qubell (jb-05-to-07.zip) using jbhook
|
||||
* jubeat clan (jb-08.zip) using jbhook
|
||||
* SOUND VOLTEX
|
||||
* SOUND VOLTEX BOOTH (sdvx.zip)
|
||||
* SOUND VOLTEX II -infinite infection- (sdvx.zip)
|
||||
* SOUND VOLTEX III GRAVITY WARS (sdvx.zip)
|
||||
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx.zip)
|
||||
* SOUND VOLTEX BOOTH (sdvx.zip) using sdvxhook
|
||||
* SOUND VOLTEX II -infinite infection- (sdvx.zip) using sdvxhook
|
||||
* SOUND VOLTEX III GRAVITY WARS (sdvx.zip) using sdvxhook
|
||||
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx.zip) using sdvxhook
|
||||
* SOUND VOLTEX Vivid Wave (sdvx2.zip) using sdvxhook2
|
||||
|
||||
# Supported platforms
|
||||
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
|
||||
|
||||
2
dist/bst/config.bat
vendored
2
dist/bst/config.bat
vendored
@@ -1 +1 @@
|
||||
@start config bst
|
||||
@start config.exe bst
|
||||
|
||||
2
dist/ddr/config.bat
vendored
2
dist/ddr/config.bat
vendored
@@ -1 +1 @@
|
||||
@start config ddr
|
||||
@start config.exe ddr
|
||||
|
||||
2
dist/iidx/config.bat
vendored
2
dist/iidx/config.bat
vendored
@@ -1 +1 @@
|
||||
@start config iidx
|
||||
@start config.exe iidx
|
||||
|
||||
16
dist/iidx/gamestart-26.bat
vendored
Normal file
16
dist/iidx/gamestart-26.bat
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
cd /d %~dp0
|
||||
|
||||
if not exist dev mkdir dev
|
||||
if not exist dev\e mkdir dev\e
|
||||
if not exist dev\g mkdir dev\g
|
||||
if not exist dev\nvram mkdir dev\nvram
|
||||
if not exist dev\raw mkdir dev\raw
|
||||
if not exist dev\raw\log mkdir dev\raw\log
|
||||
if not exist dev\raw\fscache mkdir dev\raw\fscache
|
||||
|
||||
for /R prop\defaults %%D in (*.*) do (
|
||||
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
|
||||
)
|
||||
|
||||
launcher -H 134217728 -K iidxhook8.dll bm2dx.dll --config iidxhook-26.conf %*
|
||||
47
dist/iidx/iidxhook-26.conf
vendored
Normal file
47
dist/iidx/iidxhook-26.conf
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# Fix stretched BG videos on newer GPUs. Might appear on Red and newer
|
||||
gfx.bgvideo_uv_fix=false
|
||||
|
||||
# Run the game in a framed window (requires windowed option)
|
||||
gfx.framed=false
|
||||
|
||||
# Software limit the frame rate of the rendering loop in hz, e.g. 60 or 59.95 (0.0 = no software limit)
|
||||
gfx.frame_rate_limit=0.0
|
||||
|
||||
# Patch the GPU device ID detection (leave empty to disable), format XXXX:YYYY, two 4 digit hex numbers (vid:pid). Examples: 1002:7146 (RV515, Radeon X1300), 1002:95C5 (RV620 LE, Radeon HD3450)
|
||||
gfx.pci_id=1002:7146
|
||||
|
||||
# Run the game windowed
|
||||
gfx.windowed=false
|
||||
|
||||
# Windowed width, 0 for default size
|
||||
gfx.window_width=0
|
||||
|
||||
# Windowed height, 0 for default size
|
||||
gfx.window_height=0
|
||||
|
||||
# Up-/downscale the back buffer's width. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding height parameter.
|
||||
gfx.scale_back_buffer_width=0
|
||||
|
||||
# Up-/downscale the back buffer's height. This does not change the game's rendering resolution but scales the final frame. Use this to target the native resolution of your monitor/TV, e.g. to avoid over-/underscan, bad image quality or latency caused by the monitors internal upscaler. 0 to disable this feature. Must be set in combination with the corresponding width parameter.
|
||||
gfx.scale_back_buffer_height=0
|
||||
|
||||
# Filter type to use for up-/downscaling the back buffer. Only used if scaling feature was enabled by setting the scaling width and height parameters. Available types: none, linear, point (refer to D3DTEXTUREFILTERTYPE for explanation).
|
||||
gfx.scale_back_buffer_filter=none
|
||||
|
||||
# Disables the camera emulation
|
||||
cam.disable_emu=false
|
||||
|
||||
# Override camera device ID 1 detection (copy from device manager, do not escape)
|
||||
cam.device_id1=
|
||||
|
||||
# Override camera device ID 2 detection (copy from device manager, do not escape)
|
||||
cam.device_id2=
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM0 (for games supporting slotted readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable BIO2 emulation and enable usage of real BIO2 hardware
|
||||
io.disable_bio2_emu=false
|
||||
|
||||
# Disables the poll limiter, warning very high CPU usage may arise
|
||||
io.disable_poll_limiter=false
|
||||
2
dist/jb/config.bat
vendored
2
dist/jb/config.bat
vendored
@@ -1 +1 @@
|
||||
@start config jb
|
||||
@start config.exe jb
|
||||
|
||||
2
dist/old/config-dm.bat
vendored
2
dist/old/config-dm.bat
vendored
@@ -1 +1 @@
|
||||
@start config dm
|
||||
@start config.exe dm
|
||||
|
||||
2
dist/old/config-gf.bat
vendored
2
dist/old/config-gf.bat
vendored
@@ -1 +1 @@
|
||||
@start config gf
|
||||
@start config.exe gf
|
||||
|
||||
2
dist/old/config-pnm.bat
vendored
2
dist/old/config-pnm.bat
vendored
@@ -1 +1 @@
|
||||
@start config pnm
|
||||
@start config.exe pnm
|
||||
|
||||
2
dist/old/config-sdvx.bat
vendored
2
dist/old/config-sdvx.bat
vendored
@@ -1 +1 @@
|
||||
@start config sdvx
|
||||
@start config.exe sdvx
|
||||
|
||||
2
dist/sdvx/config.bat
vendored
2
dist/sdvx/config.bat
vendored
@@ -1 +1 @@
|
||||
@start config sdvx
|
||||
@start config.exe sdvx
|
||||
|
||||
1
dist/sdvx5/config.bat
vendored
Normal file
1
dist/sdvx5/config.bat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
@start config.exe sdvx
|
||||
16
dist/sdvx5/gamestart.bat
vendored
Normal file
16
dist/sdvx5/gamestart.bat
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
cd /d %~dp0
|
||||
|
||||
if not exist dev mkdir dev
|
||||
if not exist dev\e mkdir dev\e
|
||||
if not exist dev\g mkdir dev\g
|
||||
if not exist dev\nvram mkdir dev\nvram
|
||||
if not exist dev\raw mkdir dev\raw
|
||||
if not exist dev\raw\log mkdir dev\raw\log
|
||||
if not exist dev\raw\fscache mkdir dev\raw\fscache
|
||||
|
||||
for /R prop\defaults %%D in (*.*) do (
|
||||
if not exist dev\nvram\%%~nxD copy /y prop\defaults\%%~nxD dev\nvram
|
||||
)
|
||||
|
||||
launcher -H 268435456 -K sdvxhook2.dll soundvoltex.dll --options sdvxhook2.conf %*
|
||||
27
dist/sdvx5/sdvxhook2.conf
vendored
Normal file
27
dist/sdvx5/sdvxhook2.conf
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM2
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable BIO2 emulation and enable usage of real BIO2 hardware
|
||||
io.disable_bio2_emu=false
|
||||
|
||||
# Disables the poll limiter, warning very high CPU usage may arise
|
||||
io.disable_poll_limiter=false
|
||||
|
||||
# Run the game in a framed window (requires windowed option)
|
||||
gfx.framed=true
|
||||
|
||||
# Run the game windowed
|
||||
gfx.windowed=false
|
||||
|
||||
# Windowed width, -1 for default size
|
||||
gfx.window_width=720
|
||||
|
||||
# Windowed height, -1 for default size
|
||||
gfx.window_height=1280
|
||||
|
||||
# Disables the camera emulation
|
||||
cam.disable_emu=false
|
||||
|
||||
# Override camera device ID detection (copy from device manager, do not escape)
|
||||
cam.device_id1=
|
||||
|
||||
@@ -44,10 +44,30 @@ make
|
||||
|
||||
All output is located in the *build* folder including the final *bemanitools.zip* package.
|
||||
|
||||
### Release building
|
||||
A release build is a clean build including code formatting and testing. This can be executed by running the following
|
||||
command:
|
||||
```
|
||||
make release
|
||||
```
|
||||
|
||||
## Code formatting
|
||||
To apply our code style using clang-format, simply run the following command:
|
||||
```
|
||||
make code-format
|
||||
```
|
||||
|
||||
Please also refer to the [section about](###Additional-code-style-guidelines) which cannot be covered using
|
||||
clang-format.
|
||||
|
||||
## Testing
|
||||
This still needs to be improved/implemented properly to run the unit-tests easily. Currently, you have to be on either
|
||||
a Linux/MacOSX system to run *run-test-wine.sh* from the root folder. This executes all currently available unit-tests
|
||||
and reports to the terminal any errors. This requires wine to be installed.
|
||||
a Linux/MacOSX system and run
|
||||
```
|
||||
make run-tests
|
||||
```
|
||||
This executes all currently available unit-tests and reports to the terminal any errors. This requires wine to be
|
||||
installed.
|
||||
|
||||
## Project structure
|
||||
Now that your setup is ready to go, here is brief big picture of what you find in this project.
|
||||
@@ -140,6 +160,26 @@ if (var == 2) {
|
||||
printf("%d\n", var);
|
||||
```
|
||||
|
||||
#### Empty line at the start of blocks
|
||||
There are situations when you want to have an empty line at the start of the block to enhance readability, for example:
|
||||
```
|
||||
if (a &&
|
||||
b &&
|
||||
c) {
|
||||
d = 5;
|
||||
}
|
||||
```
|
||||
|
||||
Here the assignment aligns with the conditions of the if-black making it hard to read. Better:
|
||||
```
|
||||
if (a &&
|
||||
b &&
|
||||
c) {
|
||||
|
||||
d = 5;
|
||||
}
|
||||
```
|
||||
|
||||
#### Includes
|
||||
* Always keep all includes at the top of a header and source file. Exception: Documentation before include guards on
|
||||
header file.
|
||||
@@ -291,6 +331,20 @@ Upper-case with underscore as spacing, proper namespacing to namespace and modul
|
||||
#define EZUSB_DEVICE_VID 0xFFFF
|
||||
```
|
||||
|
||||
#### Multiple variable declarations
|
||||
Only one declaration per line which also avoids various errors, for example:
|
||||
```
|
||||
// Nope
|
||||
char a, b, b;
|
||||
```
|
||||
|
||||
```
|
||||
// Ok
|
||||
char a;
|
||||
char b;
|
||||
char c;
|
||||
```
|
||||
|
||||
### Testing
|
||||
We advice you to write unit tests for all modules that allow proper unit testing. This applies to modules that are not
|
||||
part of the actual hooking process and do not rely on external devices to be available. Add these tests to the
|
||||
|
||||
@@ -4,6 +4,11 @@ iidxhook is a collection of hook libraries for BeatmaniaIIDX providing
|
||||
emulation and various patches to run these games on non BemaniPC hardware and
|
||||
newer Windows versions.
|
||||
|
||||
The hook libraries must be bootstrapped either using [inject](../inject.md) or
|
||||
[launcher](../launcher.md) depending on the version you want to run. Further
|
||||
instructions are given in dedicated readme files for each iidxhook version
|
||||
(see below).
|
||||
|
||||
# Versions
|
||||
|
||||
iidxhook comes in a few different flavors. The game and its engine changed over
|
||||
|
||||
@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
|
||||
* RED
|
||||
* HAPPY SKY
|
||||
|
||||
The games must be bootstrapped using [inject](../inject.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
Ensure your folder with your unpacked data looks like this:
|
||||
@@ -24,12 +26,6 @@ integrated sound chip, you have to replace RtEffect.dll with a stubbed/patched
|
||||
version (RtEffect_patched.dll). Otherwise, the game might crash instantly when
|
||||
trying to start it.
|
||||
|
||||
In order to use the gfx feature patches, e.g. window mode, monitor check,
|
||||
frame rate locking, framebuffer up/-downscaling etc. you have to use the
|
||||
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
|
||||
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
|
||||
due to compatibility and maintainability reasons.
|
||||
|
||||
Run the appropriate gamestart-XX.bat file as admin, where XX is either
|
||||
09, 10, 11, 12.
|
||||
|
||||
@@ -58,6 +54,14 @@ to have a pre-ceeding "-p" for every parameter added.
|
||||
However, if a parameter is specifed in the configuration file and as a command
|
||||
line argument, the command line argument overrides the config file's value.
|
||||
|
||||
# Use d3d8to9 wrapper
|
||||
|
||||
In order to use the gfx feature patches, e.g. window mode, monitor check,
|
||||
frame rate locking, framebuffer up/-downscaling etc. you **must** use the
|
||||
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
|
||||
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
|
||||
due to compatibility and maintainability reasons.
|
||||
|
||||
# Eamuse network setup
|
||||
|
||||
If you want to run the games online, you have to set a valid PCBID in the
|
||||
@@ -122,6 +126,10 @@ happens, run the game again.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
|
||||
## Window mode or any other gfx related options do not work when changing them in the config file or using cmd args
|
||||
|
||||
See [this](#Use-d3d8to9-wrapper) section.
|
||||
|
||||
## The game does not run "well" (frame drops, drifting offsync etc)
|
||||
This can be related to various issues:
|
||||
* Make sure to run the game as (true) Administrator especially on Windows 7 and
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
The following games are compatible with this version of iidxhook:
|
||||
* DistorteD
|
||||
|
||||
The games must be bootstrapped using [inject](../inject.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
Ensure your folder with your unpacked data looks like this:
|
||||
@@ -21,12 +23,6 @@ integrated sound chip, you have to replace RtEffect.dll with a stubbed/patched
|
||||
version (RtEffect_patched.dll). Otherwise, the game might crash instantly when
|
||||
trying to start it.
|
||||
|
||||
In order to use the gfx feature patches, e.g. window mode, monitor check,
|
||||
frame rate locking, framebuffer up/-downscaling etc. you have to use the
|
||||
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
|
||||
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
|
||||
due to compatibility and maintainability reasons.
|
||||
|
||||
Run the gamestart-13.bat file as admin.
|
||||
|
||||
# Configuring iidxhook
|
||||
@@ -54,6 +50,14 @@ to have a pre-ceeding "-p" for every parameter added.
|
||||
However, if a parameter is specifed in the configuration file and as a command
|
||||
line argument, the command line argument overrides the config file's value.
|
||||
|
||||
# Use d3d8to9 wrapper
|
||||
|
||||
In order to use the gfx feature patches, e.g. window mode, monitor check,
|
||||
frame rate locking, framebuffer up/-downscaling etc. you **must** use the
|
||||
d3d8to9 wrapper library (get it from the bemanitools-supplement package).
|
||||
Bemanitools removed the old d3d8 hooking module to provide native d3d8 hooks
|
||||
due to compatibility and maintainability reasons.
|
||||
|
||||
# Eamuse network setup
|
||||
|
||||
If you want to run the games online, you have to set a valid PCBID in the
|
||||
@@ -98,6 +102,10 @@ happens, run the game again.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
|
||||
## Window mode or any other gfx related options do not work when changing them in the config file or using cmd args
|
||||
|
||||
See [this](#Use-d3d8to9-wrapper) section.
|
||||
|
||||
## The game does not run "well" (frame drops, drifting offsync etc)
|
||||
This can be related to various issues:
|
||||
* Make sure to run the game as (true) Administrator especially on Windows 7 and
|
||||
|
||||
@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
|
||||
* EMPRESS
|
||||
* SIRIUS
|
||||
|
||||
The games must be bootstrapped using [inject](../inject.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
Ensure your folder with your unpacked data looks like this:
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
The following games are compatible with this version of iidxhook:
|
||||
* Resort Anthem
|
||||
|
||||
The games must be bootstrapped using [launcher](../launcher.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
The following games are compatible with this version of iidxhook:
|
||||
* Lincle
|
||||
|
||||
The games must be bootstrapped using [launcher](../launcher.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
The following games are compatible with this version of iidxhook:
|
||||
* Tricoro
|
||||
|
||||
The games must be bootstrapped using [launcher](../launcher.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")
|
||||
|
||||
@@ -6,6 +6,8 @@ The following games are compatible with this version of iidxhook:
|
||||
* copula
|
||||
* SINOBUZ
|
||||
|
||||
The games must be bootstrapped using [launcher](../launcher.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
We assume that you are using a clean/vanilla data dump. Ensure your ("concents")
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
The following games are compatible with this version of iidxhook:
|
||||
* CANNON BALLERS
|
||||
|
||||
The games must be bootstrapped using [launcher](../launcher.md).
|
||||
|
||||
# Data setup and running the game
|
||||
|
||||
## Supported versions of Windows
|
||||
|
||||
18
doc/inject.md
Normal file
18
doc/inject.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Inject
|
||||
|
||||
Inject is a tool that creates a process for a specified application executable
|
||||
file and injects a specified list of library/dll files into the process before
|
||||
it is kicked off.
|
||||
|
||||
Typically, the tool is run when you use one of the bat script files to start
|
||||
any of the games that require its usage, e.g. older IIDX games.
|
||||
|
||||
It comes with further option switches for development, e.g. Halting until
|
||||
a debugger is attached, outputting debug output to a logfile etc.
|
||||
Just run the application without any parameters to get a usage message:
|
||||
```
|
||||
inject.exe
|
||||
```
|
||||
|
||||
How inject.exe is used can be taken from the bat script files of various
|
||||
(typically older) games.
|
||||
15
doc/launcher.md
Normal file
15
doc/launcher.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Launcher
|
||||
|
||||
Launcher is a tool which is required to run the more recent titles. It sets up
|
||||
the AVS environment for the target game to boot before it runs the it.
|
||||
|
||||
Typically, the tool is run when you use one of the bat script files to start
|
||||
any of the games that require its usage, e.g. newer IIDX games.
|
||||
|
||||
It comes with option switches to configure the AVS environment and for
|
||||
development, e.g. Halting until a debugger is attached, outputting debug
|
||||
output to a logfile etc.
|
||||
Just run the application without any parameters to get a usage message:
|
||||
```
|
||||
launcher.exe
|
||||
```
|
||||
16
doc/sdvxhook/sdvxio-kfca.md
Normal file
16
doc/sdvxhook/sdvxio-kfca.md
Normal file
@@ -0,0 +1,16 @@
|
||||
This library talks to a KFCA node through ACIO and implements the sdvxio API of BT5.
|
||||
Thus, it allows you to use a KFCA device board with *any* version of SDVX that is supported by BT5.
|
||||
|
||||
# Setup
|
||||
* Rename sdvxio-kfca.dll to sdvxio.dll.
|
||||
* Ensure that your gamestart.bat actually injects the appropriate sdvxhook dll
|
||||
for example:
|
||||
```
|
||||
launcher -K sdvxhook2.dll soundvoltex.dll ...*
|
||||
```
|
||||
or that the application otherwise uses sdvxio.dll
|
||||
|
||||
* sdvxio-kfca expects a KFCA device on COM3 by default
|
||||
* You can change the port and baudrate by editing the sdvxio-kfca.conf that should be created by default
|
||||
* If there is also an ICCA device on the same ACIO bus, it cannot be used with eamio-icca at this time
|
||||
* Please connect any additional acio devices to their own port (ex: SDVX5 expects an ICCA by itself on COM2)
|
||||
@@ -25,27 +25,33 @@ enum SensorTestMode;
|
||||
enum SMXUpdateCallbackReason;
|
||||
struct SMXSensorTestModeData;
|
||||
|
||||
// All functions are nonblocking. Getters will return the most recent state. Setters will
|
||||
// return immediately and do their work in the background. No functions return errors, and
|
||||
// setting data on a pad which isn't connected will have no effect.
|
||||
// All functions are nonblocking. Getters will return the most recent state.
|
||||
// Setters will return immediately and do their work in the background. No
|
||||
// functions return errors, and setting data on a pad which isn't connected will
|
||||
// have no effect.
|
||||
|
||||
// Initialize, and start searching for devices.
|
||||
//
|
||||
// UpdateCallback will be called when something happens: connection or disconnection, inputs
|
||||
// changed, configuration updated, test data updated, etc. It doesn't specify what's changed,
|
||||
// and the user should check all state that it's interested in.
|
||||
// UpdateCallback will be called when something happens: connection or
|
||||
// disconnection, inputs changed, configuration updated, test data updated, etc.
|
||||
// It doesn't specify what's changed, and the user should check all state that
|
||||
// it's interested in.
|
||||
//
|
||||
// This is called asynchronously from a helper thread, so the receiver must be thread-safe.
|
||||
typedef void SMXUpdateCallback(int pad, enum SMXUpdateCallbackReason reason, void *pUser);
|
||||
SMX_EXTERN_C SMX_API void SMX_Start(SMXUpdateCallback UpdateCallback, void *pUser);
|
||||
// This is called asynchronously from a helper thread, so the receiver must be
|
||||
// thread-safe.
|
||||
typedef void
|
||||
SMXUpdateCallback(int pad, enum SMXUpdateCallbackReason reason, void *pUser);
|
||||
SMX_EXTERN_C SMX_API void
|
||||
SMX_Start(SMXUpdateCallback UpdateCallback, void *pUser);
|
||||
|
||||
// Shut down and disconnect from all devices. This will wait for any user callbacks to complete,
|
||||
// and no user callbacks will be called after this returns. This must not be called from within
|
||||
// the update callback.
|
||||
// Shut down and disconnect from all devices. This will wait for any user
|
||||
// callbacks to complete, and no user callbacks will be called after this
|
||||
// returns. This must not be called from within the update callback.
|
||||
SMX_EXTERN_C SMX_API void SMX_Stop();
|
||||
|
||||
// Set a function to receive diagnostic logs. By default, logs are written to stdout.
|
||||
// This can be called before SMX_Start, so it affects any logs sent during initialization.
|
||||
// Set a function to receive diagnostic logs. By default, logs are written to
|
||||
// stdout. This can be called before SMX_Start, so it affects any logs sent
|
||||
// during initialization.
|
||||
typedef void SMXLogCallback(const char *log);
|
||||
SMX_EXTERN_C SMX_API void SMX_SetLogCallback(SMXLogCallback callback);
|
||||
|
||||
@@ -55,8 +61,9 @@ SMX_EXTERN_C SMX_API void SMX_GetInfo(int pad, struct SMXInfo *info);
|
||||
// Get a mask of the currently pressed panels.
|
||||
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
|
||||
|
||||
// Update the lights. Both pads are always updated together. lightsData is a list of 8-bit RGB
|
||||
// colors, one for each LED. Each panel has lights in the following order:
|
||||
// Update the lights. Both pads are always updated together. lightsData is a
|
||||
// list of 8-bit RGB colors, one for each LED. Each panel has lights in the
|
||||
// following order:
|
||||
//
|
||||
// 0123
|
||||
// 4567
|
||||
@@ -69,61 +76,70 @@ SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
|
||||
// 345 CDE
|
||||
// 678 F01
|
||||
//
|
||||
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has 864 bytes of data.
|
||||
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has
|
||||
// 864 bytes of data.
|
||||
//
|
||||
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a best effort will be
|
||||
// made to send the most recent lights data available, but the panels won't update more quickly.
|
||||
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a
|
||||
// best effort will be made to send the most recent lights data available, but
|
||||
// the panels won't update more quickly.
|
||||
//
|
||||
// The panels will return to automatic lighting if no lights are received for a while, so applications
|
||||
// controlling lights should send light updates continually, even if the lights aren't changing.
|
||||
// The panels will return to automatic lighting if no lights are received for a
|
||||
// while, so applications controlling lights should send light updates
|
||||
// continually, even if the lights aren't changing.
|
||||
SMX_EXTERN_C SMX_API void SMX_SetLights(const char lightsData[864]);
|
||||
|
||||
// By default, the panels light automatically when stepped on. If a lights command is sent by
|
||||
// the application, this stops happening to allow the application to fully control lighting.
|
||||
// If no lights update is received for a few seconds, automatic lighting is reenabled by the
|
||||
// panels.
|
||||
// By default, the panels light automatically when stepped on. If a lights
|
||||
// command is sent by the application, this stops happening to allow the
|
||||
// application to fully control lighting. If no lights update is received for a
|
||||
// few seconds, automatic lighting is reenabled by the panels.
|
||||
//
|
||||
// SMX_ReenableAutoLights can be called to immediately reenable auto-lighting, without waiting
|
||||
// for the timeout period to elapse. Games don't need to call this, since the panels will return
|
||||
// to auto-lighting mode automatically after a brief period of no updates.
|
||||
// SMX_ReenableAutoLights can be called to immediately reenable auto-lighting,
|
||||
// without waiting for the timeout period to elapse. Games don't need to call
|
||||
// this, since the panels will return to auto-lighting mode automatically after
|
||||
// a brief period of no updates.
|
||||
SMX_EXTERN_C SMX_API void SMX_ReenableAutoLights();
|
||||
|
||||
// Get the current controller's configuration.
|
||||
//
|
||||
// Return true if a configuration is available. If false is returned, no panel is connected
|
||||
// and no data will be set.
|
||||
// Return true if a configuration is available. If false is returned, no panel
|
||||
// is connected and no data will be set.
|
||||
SMX_EXTERN_C SMX_API bool SMX_GetConfig(int pad, struct SMXConfig *config);
|
||||
|
||||
// Update the current controller's configuration. This doesn't block, and the new configuration will
|
||||
// be sent in the background. SMX_GetConfig will return the new configuration as soon as this call
|
||||
// returns, without waiting for it to actually be sent to the controller.
|
||||
SMX_EXTERN_C SMX_API void SMX_SetConfig(int pad, const struct SMXConfig *config);
|
||||
// Update the current controller's configuration. This doesn't block, and the
|
||||
// new configuration will be sent in the background. SMX_GetConfig will return
|
||||
// the new configuration as soon as this call returns, without waiting for it to
|
||||
// actually be sent to the controller.
|
||||
SMX_EXTERN_C SMX_API void
|
||||
SMX_SetConfig(int pad, const struct SMXConfig *config);
|
||||
|
||||
// Reset a pad to its original configuration.
|
||||
SMX_EXTERN_C SMX_API void SMX_FactoryReset(int pad);
|
||||
|
||||
// Request an immediate panel recalibration. This is normally not necessary, but can be helpful
|
||||
// for diagnostics.
|
||||
// Request an immediate panel recalibration. This is normally not necessary,
|
||||
// but can be helpful for diagnostics.
|
||||
SMX_EXTERN_C SMX_API void SMX_ForceRecalibration(int pad);
|
||||
|
||||
// Set a panel test mode and request test data. This is used by the configuration tool.
|
||||
// Set a panel test mode and request test data. This is used by the
|
||||
// configuration tool.
|
||||
SMX_EXTERN_C SMX_API void SMX_SetTestMode(int pad, enum SensorTestMode mode);
|
||||
SMX_EXTERN_C SMX_API bool SMX_GetTestData(int pad, struct SMXSensorTestModeData *data);
|
||||
SMX_EXTERN_C SMX_API bool
|
||||
SMX_GetTestData(int pad, struct SMXSensorTestModeData *data);
|
||||
|
||||
// Return the build version of the DLL, which is based on the git tag at build time. This
|
||||
// is only intended for diagnostic logging, and it's also the version we show in SMXConfig.
|
||||
// Return the build version of the DLL, which is based on the git tag at build
|
||||
// time. This is only intended for diagnostic logging, and it's also the
|
||||
// version we show in SMXConfig.
|
||||
SMX_EXTERN_C SMX_API const char *SMX_Version();
|
||||
|
||||
// General info about a connected controller. This can be retrieved with SMX_GetInfo.
|
||||
struct SMXInfo
|
||||
{
|
||||
// True if we're fully connected to this controller. If this is false, the other
|
||||
// fields won't be set.
|
||||
// General info about a connected controller. This can be retrieved with
|
||||
// SMX_GetInfo.
|
||||
struct SMXInfo {
|
||||
// True if we're fully connected to this controller. If this is false, the
|
||||
// other fields won't be set.
|
||||
bool m_bConnected;
|
||||
|
||||
// This device's serial number. This can be used to distinguish devices from each
|
||||
// other if more than one is connected. This is a null-terminated string instead
|
||||
// of a C++ string for C# marshalling.
|
||||
// This device's serial number. This can be used to distinguish devices
|
||||
// from each other if more than one is connected. This is a null-terminated
|
||||
// string instead of a C++ string for C# marshalling.
|
||||
char m_Serial[33];
|
||||
|
||||
// This device's firmware version.
|
||||
@@ -131,22 +147,24 @@ struct SMXInfo
|
||||
};
|
||||
|
||||
enum SMXUpdateCallbackReason {
|
||||
// This is called when a generic state change happens: connection or disconnection, inputs changed,
|
||||
// test data updated, etc. It doesn't specify what's changed. We simply check the whole state.
|
||||
// This is called when a generic state change happens: connection or
|
||||
// disconnection, inputs changed,
|
||||
// test data updated, etc. It doesn't specify what's changed. We simply
|
||||
// check the whole state.
|
||||
SMXUpdateCallback_Updated,
|
||||
|
||||
// This is called when SMX_FactoryReset completes, indicating that SMX_GetConfig will now return
|
||||
// This is called when SMX_FactoryReset completes, indicating that
|
||||
// SMX_GetConfig will now return
|
||||
// the reset configuration.
|
||||
SMXUpdateCallback_FactoryResetCommandComplete
|
||||
};
|
||||
|
||||
// The configuration for a connected controller. This can be retrieved with SMX_GetConfig
|
||||
// and modified with SMX_SetConfig.
|
||||
// The configuration for a connected controller. This can be retrieved with
|
||||
// SMX_GetConfig and modified with SMX_SetConfig.
|
||||
//
|
||||
// The order and packing of this struct corresponds to the configuration packet sent to
|
||||
// the master controller, so it must not be changed.
|
||||
struct SMXConfig
|
||||
{
|
||||
// The order and packing of this struct corresponds to the configuration packet
|
||||
// sent to the master controller, so it must not be changed.
|
||||
struct SMXConfig {
|
||||
#if 0
|
||||
// These fields are unused and must be left at their existing values.
|
||||
uint8_t unused1 = 0xFF, unused2 = 0xFF;
|
||||
@@ -228,9 +246,10 @@ struct SMXConfig
|
||||
uint8_t panelThreshold8Low, panelThreshold8High;
|
||||
#endif
|
||||
};
|
||||
//static_assert(sizeof(SMXConfig) == 84, "Expected 84 bytes");
|
||||
// static_assert(sizeof(SMXConfig) == 84, "Expected 84 bytes");
|
||||
|
||||
// The values (except for Off) correspond with the protocol and must not be changed.
|
||||
// The values (except for Off) correspond with the protocol and must not be
|
||||
// changed.
|
||||
enum SensorTestMode {
|
||||
SensorTestMode_Off = 0,
|
||||
// Return the raw, uncalibrated value of each sensor.
|
||||
@@ -246,10 +265,11 @@ enum SensorTestMode {
|
||||
SensorTestMode_Tare = '3',
|
||||
};
|
||||
|
||||
// Data for the current SensorTestMode. The interpretation of sensorLevel depends on the mode.
|
||||
struct SMXSensorTestModeData
|
||||
{
|
||||
// If false, sensorLevel[n][*] is zero because we didn't receive a response from that panel.
|
||||
// Data for the current SensorTestMode. The interpretation of sensorLevel
|
||||
// depends on the mode.
|
||||
struct SMXSensorTestModeData {
|
||||
// If false, sensorLevel[n][*] is zero because we didn't receive a response
|
||||
// from that panel.
|
||||
bool bHaveDataFromPanel[9];
|
||||
|
||||
int16_t sensorLevel[9][4];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef IMPORTS_AVS_EA3_H
|
||||
#define IMPORTS_AVS_EA3_H
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
void ea3_boot(struct property_node *conf);
|
||||
void ea3_shutdown(void);
|
||||
|
||||
|
||||
@@ -74,45 +74,44 @@ struct property_psmap {
|
||||
intptr_t xdefault;
|
||||
};
|
||||
|
||||
#define PSMAP_BEGIN(name) \
|
||||
struct property_psmap name[] = {
|
||||
|
||||
#define PSMAP_BEGIN(name) struct property_psmap name[] = {
|
||||
#define PSMAP_REQUIRED(type, xstruct, field, path) \
|
||||
{ \
|
||||
type, \
|
||||
0, \
|
||||
offsetof(xstruct, field), \
|
||||
sizeof( ((xstruct *) 0)->field ), \
|
||||
path, \
|
||||
0, \
|
||||
}, \
|
||||
{ \
|
||||
type, \
|
||||
0, \
|
||||
offsetof(xstruct, field), \
|
||||
sizeof(((xstruct *) 0)->field), \
|
||||
path, \
|
||||
0, \
|
||||
},
|
||||
|
||||
#define PSMAP_OPTIONAL(type, xstruct, field, path, xdefault) \
|
||||
{ \
|
||||
type, \
|
||||
PSMAP_FLAG_HAVE_DEFAULT, \
|
||||
offsetof(xstruct, field), \
|
||||
sizeof( ((xstruct *) 0)->field ), \
|
||||
path, \
|
||||
(intptr_t) xdefault, \
|
||||
}, \
|
||||
{ \
|
||||
type, \
|
||||
PSMAP_FLAG_HAVE_DEFAULT, \
|
||||
offsetof(xstruct, field), \
|
||||
sizeof(((xstruct *) 0)->field), \
|
||||
path, \
|
||||
(intptr_t) xdefault, \
|
||||
},
|
||||
|
||||
#define PSMAP_END \
|
||||
{ 0xFF, 0, 0, 0, NULL, 0 } \
|
||||
};
|
||||
#define PSMAP_END \
|
||||
{ \
|
||||
0xFF, 0, 0, 0, NULL, 0 \
|
||||
} \
|
||||
} \
|
||||
;
|
||||
|
||||
#if AVS_VERSION >= 1500
|
||||
# define AVS_LOG_WRITER(name, chars, nchars, ctx) \
|
||||
void name(const char * chars , uint32_t nchars , void * ctx )
|
||||
#define AVS_LOG_WRITER(name, chars, nchars, ctx) \
|
||||
void name(const char *chars, uint32_t nchars, void *ctx)
|
||||
|
||||
typedef void (*avs_log_writer_t)(const char *chars, uint32_t nchars,
|
||||
void *ctx);
|
||||
typedef void (*avs_log_writer_t)(const char *chars, uint32_t nchars, void *ctx);
|
||||
#else
|
||||
# define AVS_LOG_WRITER(name, chars, nchars, ctx) \
|
||||
void name(void * ctx , const char * chars , uint32_t nchars )
|
||||
#define AVS_LOG_WRITER(name, chars, nchars, ctx) \
|
||||
void name(void *ctx, const char *chars, uint32_t nchars)
|
||||
|
||||
typedef void (*avs_log_writer_t)(void *ctx, const char *chars,
|
||||
uint32_t nchars);
|
||||
typedef void (*avs_log_writer_t)(void *ctx, const char *chars, uint32_t nchars);
|
||||
#endif
|
||||
|
||||
typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes);
|
||||
@@ -120,22 +119,38 @@ typedef int (*avs_reader_t)(uint32_t context, void *bytes, size_t nbytes);
|
||||
#if AVS_VERSION >= 1600
|
||||
/* "avs" and "std" heaps have been unified */
|
||||
typedef void (*avs_boot_t)(
|
||||
struct property_node *config, void *com_heap, size_t sz_com_heap,
|
||||
void *reserved, avs_log_writer_t log_writer, void *log_context);
|
||||
struct property_node *config,
|
||||
void *com_heap,
|
||||
size_t sz_com_heap,
|
||||
void *reserved,
|
||||
avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
|
||||
void avs_boot(
|
||||
struct property_node *config, void *com_heap, size_t sz_com_heap,
|
||||
void *reserved, avs_log_writer_t log_writer, void *log_context);
|
||||
struct property_node *config,
|
||||
void *com_heap,
|
||||
size_t sz_com_heap,
|
||||
void *reserved,
|
||||
avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
#else
|
||||
typedef void (*avs_boot_t)(
|
||||
struct property_node *config, void *std_heap, size_t sz_std_heap,
|
||||
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
|
||||
void* log_context);
|
||||
struct property_node *config,
|
||||
void *std_heap,
|
||||
size_t sz_std_heap,
|
||||
void *avs_heap,
|
||||
size_t sz_avs_heap,
|
||||
avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
|
||||
void avs_boot(
|
||||
struct property_node *config, void *std_heap, size_t sz_std_heap,
|
||||
void *avs_heap, size_t sz_avs_heap, avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
struct property_node *config,
|
||||
void *std_heap,
|
||||
size_t sz_std_heap,
|
||||
void *avs_heap,
|
||||
size_t sz_avs_heap,
|
||||
avs_log_writer_t log_writer,
|
||||
void *log_context);
|
||||
#endif
|
||||
|
||||
void avs_shutdown(void);
|
||||
@@ -149,54 +164,70 @@ void log_change_level(int level);
|
||||
|
||||
int avs_net_ctrl(int ioctl, void *bytes, uint32_t nbytes);
|
||||
|
||||
int avs_thread_create(int (*proc)(void *), void *ctx, uint32_t sz_stack,
|
||||
unsigned int priority);
|
||||
int avs_thread_create(
|
||||
int (*proc)(void *), void *ctx, uint32_t sz_stack, unsigned int priority);
|
||||
void avs_thread_destroy(int thread_id);
|
||||
void avs_thread_exit(int result);
|
||||
void avs_thread_join(int thread_id, int *result);
|
||||
|
||||
uint32_t property_read_query_memsize(
|
||||
avs_reader_t reader, uint32_t context, int unk0, int unk1);
|
||||
struct property *property_create(
|
||||
int flags, void *buffer, uint32_t buffer_size);
|
||||
avs_reader_t reader, uint32_t context, int unk0, int unk1);
|
||||
struct property *property_create(int flags, void *buffer, uint32_t buffer_size);
|
||||
struct property_node *property_search(
|
||||
struct property *prop, struct property_node *root, const char *path);
|
||||
struct property *prop, struct property_node *root, const char *path);
|
||||
int property_insert_read(
|
||||
struct property *prop, struct property_node *root, avs_reader_t reader,
|
||||
uint32_t context);
|
||||
struct property *prop,
|
||||
struct property_node *root,
|
||||
avs_reader_t reader,
|
||||
uint32_t context);
|
||||
int property_mem_write(struct property *prop, void *bytes, int nbytes);
|
||||
void *property_desc_to_buffer(struct property *prop);
|
||||
void property_file_write(struct property *prop, const char *path);
|
||||
int property_set_flag(struct property *prop, int flags, int mask);
|
||||
void property_destroy(struct property *prop);
|
||||
|
||||
int property_psmap_import(struct property *prop, struct property_node *root,
|
||||
void *dest, const struct property_psmap *psmap);
|
||||
int property_psmap_export(struct property *prop, struct property_node *root,
|
||||
const void *src, const struct property_psmap *psmap);
|
||||
int property_psmap_import(
|
||||
struct property *prop,
|
||||
struct property_node *root,
|
||||
void *dest,
|
||||
const struct property_psmap *psmap);
|
||||
int property_psmap_export(
|
||||
struct property *prop,
|
||||
struct property_node *root,
|
||||
const void *src,
|
||||
const struct property_psmap *psmap);
|
||||
|
||||
struct property_node *property_node_clone(
|
||||
struct property *new_parent, int unk0,
|
||||
struct property_node *src, bool deep);
|
||||
struct property *new_parent,
|
||||
int unk0,
|
||||
struct property_node *src,
|
||||
bool deep);
|
||||
struct property_node *property_node_create(
|
||||
struct property *prop, struct property_node *parent, int type,
|
||||
const char *key, ...);
|
||||
void property_node_name(
|
||||
struct property_node *node, char *chars, int nchars);
|
||||
struct property *prop,
|
||||
struct property_node *parent,
|
||||
int type,
|
||||
const char *key,
|
||||
...);
|
||||
void property_node_name(struct property_node *node, char *chars, int nchars);
|
||||
const char *property_node_refdata(struct property_node *node);
|
||||
int property_node_refer(struct property *prop,
|
||||
struct property_node *node, const char *name,
|
||||
enum property_type type, void *bytes, uint32_t nbytes);
|
||||
int property_node_refer(
|
||||
struct property *prop,
|
||||
struct property_node *node,
|
||||
const char *name,
|
||||
enum property_type type,
|
||||
void *bytes,
|
||||
uint32_t nbytes);
|
||||
void property_node_remove(struct property_node *node);
|
||||
enum property_type property_node_type(
|
||||
struct property_node *node);
|
||||
enum property_type property_node_type(struct property_node *node);
|
||||
struct property_node *property_node_traversal(
|
||||
struct property_node *node, enum property_node_traversal direction);
|
||||
void property_node_datasize(struct property_node* node);
|
||||
struct property_node *node, enum property_node_traversal direction);
|
||||
void property_node_datasize(struct property_node *node);
|
||||
|
||||
bool std_getenv(const char *key, char *val, uint32_t nbytes);
|
||||
void std_setenv(const char *key, const char *val);
|
||||
|
||||
void *avs_fs_mount (char* mountpoint, char* fsroot, void* fstype, int flags);
|
||||
int avs_fs_addfs(void *filesys_struct);
|
||||
int avs_fs_mount(
|
||||
const char *mountpoint, const char *fsroot, const char *fstype, void *data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@ EXPORTS
|
||||
avs_thread_destroy @7 NONAME
|
||||
avs_thread_exit @11 NONAME
|
||||
avs_thread_join @12 NONAME
|
||||
avs_fs_addfs @73 NONAME
|
||||
avs_fs_mount @76 NONAME
|
||||
avs_net_ctrl @119 NONAME
|
||||
property_create @145 NONAME
|
||||
|
||||
@@ -5,6 +5,7 @@ EXPORTS
|
||||
avs_thread_destroy @7 NONAME
|
||||
avs_thread_exit @11 NONAME
|
||||
avs_thread_join @12 NONAME
|
||||
avs_fs_addfs @73 NONAME
|
||||
avs_fs_mount @76 NONAME
|
||||
avs_net_ctrl @119 NONAME
|
||||
property_create @145 NONAME
|
||||
|
||||
@@ -8,33 +8,33 @@
|
||||
#include "acio/icca.h"
|
||||
#include "acio/kfca.h"
|
||||
|
||||
#define AC_IO_SOF 0xAA
|
||||
#define AC_IO_ESCAPE 0xFF
|
||||
#define AC_IO_RESPONSE_FLAG 0x80
|
||||
#define AC_IO_BROADCAST 0x70
|
||||
#define AC_IO_SOF 0xAA
|
||||
#define AC_IO_ESCAPE 0xFF
|
||||
#define AC_IO_RESPONSE_FLAG 0x80
|
||||
#define AC_IO_BROADCAST 0x70
|
||||
|
||||
#define ac_io_u16(x) _byteswap_ushort(x)
|
||||
#define ac_io_u32(x) _byteswap_ulong(x)
|
||||
#define ac_io_u16(x) _byteswap_ushort(x)
|
||||
#define ac_io_u32(x) _byteswap_ulong(x)
|
||||
|
||||
enum ac_io_cmd {
|
||||
AC_IO_CMD_ASSIGN_ADDRS = 0x0001,
|
||||
AC_IO_CMD_GET_VERSION = 0x0002,
|
||||
AC_IO_CMD_START_UP = 0x0003,
|
||||
AC_IO_CMD_KEEPALIVE = 0x0080,
|
||||
AC_IO_CMD_ASSIGN_ADDRS = 0x0001,
|
||||
AC_IO_CMD_GET_VERSION = 0x0002,
|
||||
AC_IO_CMD_START_UP = 0x0003,
|
||||
AC_IO_CMD_KEEPALIVE = 0x0080,
|
||||
/* Yet unknown command encountered first on jubeat (1) */
|
||||
AC_IO_CMD_UNKN_00FF = 0x00FF,
|
||||
AC_IO_CMD_CLEAR = 0x0100,
|
||||
AC_IO_CMD_UNKN_00FF = 0x00FF,
|
||||
AC_IO_CMD_CLEAR = 0x0100,
|
||||
};
|
||||
|
||||
enum ac_io_node_type {
|
||||
AC_IO_NODE_TYPE_H44B = 0x04010000,
|
||||
AC_IO_NODE_TYPE_ICCA = 0x03000000,
|
||||
AC_IO_NODE_TYPE_H44B = 0x04010000,
|
||||
AC_IO_NODE_TYPE_ICCA = 0x03000000,
|
||||
/* same as ICCA */
|
||||
AC_IO_NODE_TYPE_ICCB = 0x03000000,
|
||||
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
|
||||
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
|
||||
AC_IO_NODE_TYPE_KFCA = 0x09060000,
|
||||
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
|
||||
AC_IO_NODE_TYPE_ICCB = 0x03000000,
|
||||
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
|
||||
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
|
||||
AC_IO_NODE_TYPE_KFCA = 0x09060000,
|
||||
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@@ -52,7 +52,7 @@ struct ac_io_version {
|
||||
};
|
||||
|
||||
struct ac_io_message {
|
||||
uint8_t addr; /* High bit: clear = req, set = resp */
|
||||
uint8_t addr; /* High bit: clear = req, set = resp */
|
||||
|
||||
union {
|
||||
struct {
|
||||
@@ -76,7 +76,7 @@ struct ac_io_message {
|
||||
|
||||
struct {
|
||||
uint8_t nbytes;
|
||||
uint8_t raw[0xFF]; /* 0xFFucked if I know */
|
||||
uint8_t raw[0xFF]; /* 0xFFucked if I know */
|
||||
} bcast;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
enum ac_io_icca_cmd {
|
||||
/* Yet unknown command encountered first on jubeat (1) */
|
||||
AC_IO_ICCA_CMD_UNKN_0120 = 0x0120,
|
||||
AC_IO_ICCA_CMD_UNKN_0120 = 0x0120,
|
||||
AC_IO_ICCA_CMD_QUEUE_LOOP_START = 0x0130,
|
||||
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
|
||||
AC_IO_ICCA_CMD_POLL = 0x0134,
|
||||
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
|
||||
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
|
||||
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
|
||||
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
|
||||
AC_IO_ICCA_CMD_POLL = 0x0134,
|
||||
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
|
||||
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
|
||||
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
|
||||
};
|
||||
|
||||
enum ac_io_icca_slot_state {
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
enum ac_io_iccb_cmd {
|
||||
/* found on jubeat prop, sent after acio init req, maybe fw update? */
|
||||
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
|
||||
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
|
||||
/* found on jubeat prop, sent right after queue loop start */
|
||||
AC_IO_ICCB_CMD_UNK_0116 = 0x0116,
|
||||
AC_IO_ICCB_CMD_UNK_0116 = 0x0116,
|
||||
/* found on jubeat prop, sent after 0100 req */
|
||||
AC_IO_ICCB_CMD_UNK_0120 = 0x0120,
|
||||
AC_IO_ICCB_CMD_UNK_0120 = 0x0120,
|
||||
AC_IO_ICCB_CMD_QUEUE_LOOP_START = 0x0130,
|
||||
AC_IO_ICCB_CMD_POLL = 0x0134,
|
||||
AC_IO_ICCB_CMD_UNK_135 = 0x0135,
|
||||
AC_IO_ICCB_CMD_SLEEP = 0x013A,
|
||||
AC_IO_ICCB_CMD_READ_CARD = 0x0161
|
||||
AC_IO_ICCB_CMD_POLL = 0x0134,
|
||||
AC_IO_ICCB_CMD_UNK_135 = 0x0135,
|
||||
AC_IO_ICCB_CMD_SLEEP = 0x013A,
|
||||
AC_IO_ICCB_CMD_READ_CARD = 0x0161
|
||||
};
|
||||
|
||||
enum ac_io_iccb_sensor_state {
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#ifndef AC_IO_KFCA_H
|
||||
#define AC_IO_KFCA_H
|
||||
|
||||
#define AC_IO_CMD_KFCA_POLL 0x0113
|
||||
#define AC_IO_CMD_KFCA_WATCHDOG 0x0120
|
||||
#define AC_IO_CMD_KFCA_AMP_CONTROL 0x0128
|
||||
#define AC_IO_CMD_KFCA_POLL 0x0113
|
||||
#define AC_IO_CMD_KFCA_WATCHDOG 0x0120
|
||||
#define AC_IO_CMD_KFCA_AMP_CONTROL 0x0128
|
||||
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_COIN 0x04
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_COIN 0x04
|
||||
/* ... AC_IO_KFCA_IN_GPIO_SYS_COIN2 0x08 (maybe?) */
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_TEST 0x10
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_SERVICE 0x20
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_TEST 0x10
|
||||
#define AC_IO_KFCA_IN_GPIO_SYS_SERVICE 0x20
|
||||
|
||||
#define AC_IO_KFCA_IN_GPIO_0_C 0x0001
|
||||
#define AC_IO_KFCA_IN_GPIO_0_B 0x0002
|
||||
#define AC_IO_KFCA_IN_GPIO_0_A 0x0004
|
||||
#define AC_IO_KFCA_IN_GPIO_0_START 0x0008
|
||||
#define AC_IO_KFCA_IN_GPIO_0_RECORDER 0x0010
|
||||
#define AC_IO_KFCA_IN_GPIO_0_HEADPHONE 0x0020
|
||||
#define AC_IO_KFCA_IN_GPIO_0_C 0x0001
|
||||
#define AC_IO_KFCA_IN_GPIO_0_B 0x0002
|
||||
#define AC_IO_KFCA_IN_GPIO_0_A 0x0004
|
||||
#define AC_IO_KFCA_IN_GPIO_0_START 0x0008
|
||||
#define AC_IO_KFCA_IN_GPIO_0_RECORDER 0x0010
|
||||
#define AC_IO_KFCA_IN_GPIO_0_HEADPHONE 0x0020
|
||||
|
||||
#define AC_IO_KFCA_IN_GPIO_1_FX_R 0x0008
|
||||
#define AC_IO_KFCA_IN_GPIO_1_FX_L 0x0010
|
||||
#define AC_IO_KFCA_IN_GPIO_1_D 0x0020
|
||||
#define AC_IO_KFCA_IN_GPIO_1_FX_R 0x0008
|
||||
#define AC_IO_KFCA_IN_GPIO_1_FX_L 0x0010
|
||||
#define AC_IO_KFCA_IN_GPIO_1_D 0x0020
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
||||
@@ -43,17 +43,17 @@ static bool aciodrv_device_init(void)
|
||||
}
|
||||
|
||||
#ifdef AC_IO_MSG_LOG
|
||||
static void aciodrv_device_log_buffer(const char* msg, const uint8_t* buffer,
|
||||
int length)
|
||||
static void
|
||||
aciodrv_device_log_buffer(const char *msg, const uint8_t *buffer, int length)
|
||||
{
|
||||
char str[4096];
|
||||
|
||||
hex_encode_uc((const void*) buffer, length, str, sizeof(str));
|
||||
hex_encode_uc((const void *) buffer, length, str, sizeof(str));
|
||||
log_misc("%s, length %d: %s", msg, length, str);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool aciodrv_device_send(const uint8_t* buffer, int length)
|
||||
static bool aciodrv_device_send(const uint8_t *buffer, int length)
|
||||
{
|
||||
uint8_t send_buf[512];
|
||||
int send_buf_pos = 0;
|
||||
@@ -102,7 +102,7 @@ static bool aciodrv_device_send(const uint8_t* buffer, int length)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int aciodrv_device_receive(uint8_t* buffer, int size)
|
||||
static int aciodrv_device_receive(uint8_t *buffer, int size)
|
||||
{
|
||||
uint8_t recv_buf[512];
|
||||
int recv_size = 0;
|
||||
@@ -142,8 +142,7 @@ static int aciodrv_device_receive(uint8_t* buffer, int size)
|
||||
|
||||
/* check for escape byte. these don't count towards the
|
||||
size we expect! */
|
||||
if (recv_buf[recv_size] == AC_IO_ESCAPE)
|
||||
{
|
||||
if (recv_buf[recv_size] == AC_IO_ESCAPE) {
|
||||
/* next byte is our real data
|
||||
overwrite escape byte */
|
||||
do {
|
||||
@@ -162,7 +161,7 @@ static int aciodrv_device_receive(uint8_t* buffer, int size)
|
||||
}
|
||||
|
||||
#ifdef AC_IO_MSG_LOG
|
||||
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
|
||||
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
|
||||
#endif
|
||||
|
||||
/* recv_size - 1: omit checksum for checksum calc */
|
||||
@@ -174,12 +173,14 @@ static int aciodrv_device_receive(uint8_t* buffer, int size)
|
||||
result_size = recv_size - 1;
|
||||
|
||||
#ifdef AC_IO_MSG_LOG
|
||||
aciodrv_device_log_buffer("Recv (2)", buffer, result_size);
|
||||
aciodrv_device_log_buffer("Recv (2)", buffer, result_size);
|
||||
#endif
|
||||
|
||||
if (checksum != recv_buf[recv_size - 1]) {
|
||||
log_warning("Invalid message checksum: %02X != %02X",
|
||||
checksum, recv_buf[recv_size - 1]);
|
||||
log_warning(
|
||||
"Invalid message checksum: %02X != %02X",
|
||||
checksum,
|
||||
recv_buf[recv_size - 1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -198,7 +199,8 @@ static uint8_t aciodrv_device_enum_nodes(void)
|
||||
msg.cmd.nbytes = 1;
|
||||
msg.cmd.count = 0;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
log_warning("Enumerating nodes failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -216,13 +218,16 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
|
||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_GET_VERSION);
|
||||
msg.cmd.nbytes = 0;
|
||||
|
||||
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
||||
sizeof(struct ac_io_version))) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg,
|
||||
offsetof(struct ac_io_message, cmd.raw) +
|
||||
sizeof(struct ac_io_version))) {
|
||||
log_warning("Get version of node %d failed", node_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("Node %d: type %d, flag %d, version %d.%d.%d, product %c%c%c%c, "
|
||||
log_info(
|
||||
"Node %d: type %d, flag %d, version %d.%d.%d, product %c%c%c%c, "
|
||||
"build date: %s %s",
|
||||
node_id,
|
||||
msg.cmd.version.type,
|
||||
@@ -250,7 +255,8 @@ static bool aciodrv_device_start_node(uint8_t node_id)
|
||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_START_UP);
|
||||
msg.cmd.nbytes = 0;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
log_warning("Starting node %d failed", node_id);
|
||||
return false;
|
||||
}
|
||||
@@ -259,7 +265,7 @@ static bool aciodrv_device_start_node(uint8_t node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_device_open(const char* port, int baud)
|
||||
bool aciodrv_device_open(const char *port, int baud)
|
||||
{
|
||||
if (!aciodrv_port_open(port, baud)) {
|
||||
return false;
|
||||
@@ -275,7 +281,8 @@ bool aciodrv_device_open(const char* port, int baud)
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
|
||||
if (!aciodrv_device_get_version(i + 1, aviodrv_device_node_products[i])) {
|
||||
if (!aciodrv_device_get_version(
|
||||
i + 1, aviodrv_device_node_products[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -304,25 +311,27 @@ bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4])
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_send_and_recv(struct ac_io_message* msg, int resp_size)
|
||||
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
|
||||
{
|
||||
msg->cmd.seq_no = aciodrv_device_msg_counter++;
|
||||
|
||||
if (aciodrv_device_send((uint8_t*) msg,
|
||||
if (aciodrv_device_send(
|
||||
(uint8_t *) msg,
|
||||
offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t req_code = msg->cmd.code;
|
||||
|
||||
if (aciodrv_device_receive((uint8_t*) msg,
|
||||
resp_size) <= 0) {
|
||||
if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (req_code != msg->cmd.code) {
|
||||
log_warning("Received invalid response %04X for request %04X",
|
||||
msg->cmd.code, req_code);
|
||||
log_warning(
|
||||
"Received invalid response %04X for request %04X",
|
||||
msg->cmd.code,
|
||||
req_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* @return True if opening the port and resetting the device was successful,
|
||||
* false on error.
|
||||
*/
|
||||
bool aciodrv_device_open(const char* port, int baud);
|
||||
bool aciodrv_device_open(const char *port, int baud);
|
||||
|
||||
/**
|
||||
* Get the node count on the opened device.
|
||||
@@ -27,8 +27,8 @@ uint8_t aciodrv_device_get_node_count(void);
|
||||
*
|
||||
* @param node_id Id of the node. Needs to be in range of the total node count.
|
||||
* @param product Buffer to return the product id to.
|
||||
* @return True on success, false on error. If True the variable product contains
|
||||
* the identifier of the queried node.
|
||||
* @return True on success, false on error. If True the variable product
|
||||
* contains the identifier of the queried node.
|
||||
*/
|
||||
bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4]);
|
||||
|
||||
@@ -42,7 +42,7 @@ bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4]);
|
||||
* @param resp_size Size of the expecting response.
|
||||
* @return True on success, false on error.
|
||||
*/
|
||||
bool aciodrv_send_and_recv(struct ac_io_message* msg, int resp_size);
|
||||
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size);
|
||||
|
||||
/**
|
||||
* Close the previously opened ACIO device.
|
||||
|
||||
@@ -15,13 +15,14 @@ static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
|
||||
msg.cmd.nbytes = 1;
|
||||
msg.cmd.status = 0;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
log_warning("Starting queue loop failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("Started queue loop of node %d, status: %d",
|
||||
node_id, msg.cmd.status);
|
||||
log_info(
|
||||
"Started queue loop of node %d, status: %d", node_id, msg.cmd.status);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -35,8 +36,8 @@ bool aciodrv_icca_init(uint8_t node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
|
||||
struct ac_io_icca_state* state)
|
||||
bool aciodrv_icca_set_state(
|
||||
uint8_t node_id, int slot_state, struct ac_io_icca_state *state)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
@@ -47,8 +48,8 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
|
||||
msg.cmd.raw[0] = sizeof(struct ac_io_icca_state);
|
||||
msg.cmd.raw[1] = slot_state;
|
||||
|
||||
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
||||
msg.cmd.raw[0])) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
|
||||
log_warning("Setting state of node %d failed", node_id + 1);
|
||||
return false;
|
||||
}
|
||||
@@ -60,7 +61,7 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state)
|
||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
@@ -70,8 +71,8 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state)
|
||||
/* buffer size of data we expect */
|
||||
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
||||
|
||||
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
||||
msg.cmd.count)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
||||
log_warning("Getting state of node %d failed", node_id + 1);
|
||||
return false;
|
||||
}
|
||||
@@ -83,7 +84,7 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state* state)
|
||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
@@ -93,8 +94,8 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state* state)
|
||||
/* buffer size of data we expect */
|
||||
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
||||
|
||||
if ( !aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
||||
msg.cmd.count)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
||||
log_warning("Reading card of node %d failed", node_id + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ bool aciodrv_icca_init(uint8_t node_id);
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool aciodrv_icca_set_state(uint8_t node_id, int slot_state, struct ac_io_icca_state* state);
|
||||
bool aciodrv_icca_set_state(
|
||||
uint8_t node_id, int slot_state, struct ac_io_icca_state *state);
|
||||
|
||||
/**
|
||||
* Get the current state of an ICCA node.
|
||||
@@ -39,7 +40,7 @@ bool aciodrv_icca_set_state(uint8_t node_id, int slot_state, struct ac_io_icca_s
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state);
|
||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
|
||||
|
||||
/**
|
||||
* Trigger a card read action on the ICCA reader. Make sure to call this
|
||||
@@ -55,6 +56,6 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state* state);
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state* state);
|
||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#define LOG_MODULE "aciodrv-kfca"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aciodrv/device.h"
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
|
||||
static bool aciodrv_kfca_watchdog_start(uint8_t node_id)
|
||||
{
|
||||
|
||||
// exit early and don't actually call watchdog
|
||||
// the watchdog call actually returns different sized packets depending on the state
|
||||
// this results in an issue during packet processing (see: #68)
|
||||
// the watchdog call actually returns different sized packets depending on
|
||||
// the state this results in an issue during packet processing (see: #68)
|
||||
return true;
|
||||
|
||||
/*
|
||||
@@ -27,9 +26,8 @@ static bool aciodrv_kfca_watchdog_start(uint8_t node_id)
|
||||
msg.cmd.raw[0] = 23;
|
||||
msg.cmd.raw[1] = 112;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 2)) {
|
||||
log_warning("Starting watchdog failed");
|
||||
return false;
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
||||
2)) { log_warning("Starting watchdog failed"); return false;
|
||||
}
|
||||
|
||||
log_warning("Started watchdog of node %d, status: %d",
|
||||
@@ -54,7 +52,8 @@ static bool aciodrv_kfca_amp(uint8_t node_id)
|
||||
msg.cmd.raw[2] = 0;
|
||||
msg.cmd.raw[3] = 0;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
log_warning("Setting AMP failed");
|
||||
return false;
|
||||
}
|
||||
@@ -77,17 +76,21 @@ bool aciodrv_kfca_init(uint8_t node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aciodrv_kfca_poll(uint8_t node_id, const struct ac_io_kfca_poll_out* pout, struct ac_io_kfca_poll_in* pin)
|
||||
bool aciodrv_kfca_poll(
|
||||
uint8_t node_id,
|
||||
const struct ac_io_kfca_poll_out *pout,
|
||||
struct ac_io_kfca_poll_in *pin)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
msg.addr = node_id + 1;
|
||||
msg.addr = node_id + 1;
|
||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
|
||||
msg.cmd.nbytes = sizeof(*pout);
|
||||
/* buffer size of data we expect */
|
||||
msg.cmd.kfca_poll_out = *pout;
|
||||
|
||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||
log_warning("Polling of node %d failed", node_id + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ bool aciodrv_kfca_init(uint8_t node_id);
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool aciodrv_kfca_poll(uint8_t node_id, const struct ac_io_kfca_poll_out* pout, struct ac_io_kfca_poll_in* pin);
|
||||
bool aciodrv_kfca_poll(
|
||||
uint8_t node_id,
|
||||
const struct ac_io_kfca_poll_out *pout,
|
||||
struct ac_io_kfca_poll_in *pin);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,15 +9,21 @@
|
||||
|
||||
static HANDLE aciodrv_port_fd;
|
||||
|
||||
bool aciodrv_port_open(const char* port, int baud)
|
||||
bool aciodrv_port_open(const char *port, int baud)
|
||||
{
|
||||
COMMTIMEOUTS ct;
|
||||
DCB dcb;
|
||||
|
||||
log_info("Opening ACIO on %s at %d baud", port, baud);
|
||||
|
||||
aciodrv_port_fd = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
aciodrv_port_fd = CreateFile(
|
||||
port,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (aciodrv_port_fd == INVALID_HANDLE_VALUE) {
|
||||
log_warning("Failed to open %s", port);
|
||||
@@ -37,9 +43,9 @@ bool aciodrv_port_open(const char* port, int baud)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!PurgeComm(aciodrv_port_fd,
|
||||
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
|
||||
|
||||
if (!PurgeComm(
|
||||
aciodrv_port_fd,
|
||||
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
|
||||
log_warning("PurgeComm failed");
|
||||
|
||||
goto fail;
|
||||
@@ -143,7 +149,7 @@ int aciodrv_port_write(const void *bytes, int nbytes)
|
||||
log_warning("WriteFile failed: err = %lu", GetLastError());
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return nwrit;
|
||||
}
|
||||
@@ -154,4 +160,3 @@ void aciodrv_port_close(void)
|
||||
CloseHandle(aciodrv_port_fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef ACIODRV_PORT_H
|
||||
#define ACIODRV_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Open a serial port for communication with a ACIO device.
|
||||
@@ -12,7 +12,7 @@
|
||||
* @return True if opening the com port was successful, false on error.
|
||||
* @note This will open and setup the com port, only.
|
||||
*/
|
||||
bool aciodrv_port_open(const char* port, int baud);
|
||||
bool aciodrv_port_open(const char *port, int baud);
|
||||
|
||||
/**
|
||||
* Read data from the opened com port.
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
#include "util/log.h"
|
||||
|
||||
void ac_io_emu_cmd_assign_addrs(
|
||||
struct ac_io_emu *emu,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t node_count)
|
||||
struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t node_count)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
uint16_t cmd;
|
||||
@@ -21,9 +19,7 @@ void ac_io_emu_cmd_assign_addrs(
|
||||
cmd = ac_io_u16(req->cmd.code);
|
||||
|
||||
if (cmd != AC_IO_CMD_ASSIGN_ADDRS) {
|
||||
log_warning(
|
||||
"Address 0 expects address assignment cmd, got %04x",
|
||||
cmd);
|
||||
log_warning("Address 0 expects address assignment cmd, got %04x", cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void ac_io_emu_cmd_assign_addrs(
|
||||
struct ac_io_emu *emu,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t node_count);
|
||||
struct ac_io_emu *emu, const struct ac_io_message *req, uint8_t node_count);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <windows.h> /* Usermode API */
|
||||
#include <windows.h> /* Usermode API */
|
||||
|
||||
#include <ntdef.h> /* Kernel-mode API for ioctls */
|
||||
// clang-format off
|
||||
// Don't format because the order is important here
|
||||
#include <ntdef.h>
|
||||
#include <devioctl.h>
|
||||
#include <ntddser.h>
|
||||
// clang-format on
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -61,18 +64,26 @@ bool ac_io_emu_match_irp(const struct ac_io_emu *emu, const struct irp *irp)
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp)
|
||||
HRESULT
|
||||
ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp)
|
||||
{
|
||||
log_assert(irp != NULL);
|
||||
|
||||
switch (irp->op) {
|
||||
case IRP_OP_OPEN: return ac_io_emu_open(emu, irp);
|
||||
case IRP_OP_CLOSE: return ac_io_emu_close(emu, irp);
|
||||
case IRP_OP_READ: return ac_io_emu_read(emu, irp);
|
||||
case IRP_OP_WRITE: return ac_io_emu_write(emu, irp);
|
||||
case IRP_OP_IOCTL: return ac_io_emu_ioctl(emu, irp);
|
||||
case IRP_OP_FSYNC: return S_FALSE;
|
||||
default: return E_NOTIMPL;
|
||||
case IRP_OP_OPEN:
|
||||
return ac_io_emu_open(emu, irp);
|
||||
case IRP_OP_CLOSE:
|
||||
return ac_io_emu_close(emu, irp);
|
||||
case IRP_OP_READ:
|
||||
return ac_io_emu_read(emu, irp);
|
||||
case IRP_OP_WRITE:
|
||||
return ac_io_emu_write(emu, irp);
|
||||
case IRP_OP_IOCTL:
|
||||
return ac_io_emu_ioctl(emu, irp);
|
||||
case IRP_OP_FSYNC:
|
||||
return S_FALSE;
|
||||
default:
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,29 +140,30 @@ static HRESULT ac_io_emu_ioctl(struct ac_io_emu *emu, struct irp *irp)
|
||||
log_assert(irp != NULL);
|
||||
|
||||
switch (irp->ioctl) {
|
||||
case IOCTL_SERIAL_GET_COMMSTATUS:
|
||||
if (irp->read.bytes == NULL) {
|
||||
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
|
||||
case IOCTL_SERIAL_GET_COMMSTATUS:
|
||||
if (irp->read.bytes == NULL) {
|
||||
log_warning(
|
||||
"IOCTL_SERIAL_GET_COMMSTATUS: Output buffer is NULL");
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (irp->read.nbytes < sizeof(*status)) {
|
||||
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
|
||||
if (irp->read.nbytes < sizeof(*status)) {
|
||||
log_warning("IOCTL_SERIAL_GET_COMMSTATUS: Buffer is too small");
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
status = (SERIAL_STATUS *) irp->read.bytes;
|
||||
status->Errors = 0;
|
||||
status->AmountInInQueue = ac_io_in_is_msg_pending(&emu->in);
|
||||
status = (SERIAL_STATUS *) irp->read.bytes;
|
||||
status->Errors = 0;
|
||||
status->AmountInInQueue = ac_io_in_is_msg_pending(&emu->in);
|
||||
|
||||
irp->read.pos = sizeof(*status);
|
||||
irp->read.pos = sizeof(*status);
|
||||
|
||||
return S_FALSE;
|
||||
return S_FALSE;
|
||||
|
||||
default:
|
||||
return S_FALSE;
|
||||
default:
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,9 +182,7 @@ void ac_io_emu_request_pop(struct ac_io_emu *emu)
|
||||
}
|
||||
|
||||
void ac_io_emu_response_push(
|
||||
struct ac_io_emu *emu,
|
||||
const struct ac_io_message *resp,
|
||||
uint64_t delay_us)
|
||||
struct ac_io_emu *emu, const struct ac_io_message *resp, uint64_t delay_us)
|
||||
{
|
||||
log_assert(emu != NULL);
|
||||
log_assert(resp != NULL);
|
||||
@@ -181,14 +191,10 @@ void ac_io_emu_response_push(
|
||||
}
|
||||
|
||||
void ac_io_emu_response_push_thunk(
|
||||
struct ac_io_emu *emu,
|
||||
ac_io_in_thunk_t thunk,
|
||||
void *ctx,
|
||||
uint64_t delay_us)
|
||||
struct ac_io_emu *emu, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay_us)
|
||||
{
|
||||
log_assert(emu != NULL);
|
||||
log_assert(thunk != NULL);
|
||||
|
||||
ac_io_in_supply_thunk(&emu->in, thunk, ctx, delay_us);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,13 +27,11 @@ HRESULT ac_io_emu_dispatch_irp(struct ac_io_emu *emu, struct irp *irp);
|
||||
const struct ac_io_message *ac_io_emu_request_peek(const struct ac_io_emu *emu);
|
||||
void ac_io_emu_request_pop(struct ac_io_emu *emu);
|
||||
void ac_io_emu_response_push(
|
||||
struct ac_io_emu *emu,
|
||||
const struct ac_io_message *resp,
|
||||
uint64_t delay_ms);
|
||||
struct ac_io_emu *emu, const struct ac_io_message *resp, uint64_t delay_ms);
|
||||
void ac_io_emu_response_push_thunk(
|
||||
struct ac_io_emu *emu,
|
||||
ac_io_in_thunk_t thunk,
|
||||
void *ctx,
|
||||
uint64_t delay_ms);
|
||||
struct ac_io_emu *emu,
|
||||
ac_io_in_thunk_t thunk,
|
||||
void *ctx,
|
||||
uint64_t delay_ms);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,18 +16,15 @@
|
||||
#include "util/hex.h"
|
||||
|
||||
static void ac_io_emu_h44b_cmd_send_version(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_h44b_send_status(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
|
||||
void ac_io_emu_h44b_init(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no)
|
||||
struct ac_io_emu_h44b *h44b, struct ac_io_emu *emu, uint8_t unit_no)
|
||||
{
|
||||
memset(h44b, 0, sizeof(*h44b));
|
||||
h44b->emu = emu;
|
||||
@@ -35,8 +32,7 @@ void ac_io_emu_h44b_init(
|
||||
}
|
||||
|
||||
void ac_io_emu_h44b_dispatch_request(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req)
|
||||
{
|
||||
uint16_t cmd_code;
|
||||
|
||||
@@ -58,7 +54,8 @@ void ac_io_emu_h44b_dispatch_request(
|
||||
case AC_IO_H44B_CMD_SET_OUTPUTS:
|
||||
/* Not using the struct ac_io_h44b_output here */
|
||||
for (int i = 0; i < 6; i++) {
|
||||
jb_io_set_rgb_led((enum jb_io_rgb_led) i,
|
||||
jb_io_set_rgb_led(
|
||||
(enum jb_io_rgb_led) i,
|
||||
req->cmd.raw[i * 3],
|
||||
req->cmd.raw[i * 3 + 1],
|
||||
req->cmd.raw[i * 3 + 2]);
|
||||
@@ -71,16 +68,17 @@ void ac_io_emu_h44b_dispatch_request(
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("Unknown ACIO message %04x on h44b node, addr=%d",
|
||||
cmd_code, req->addr);
|
||||
log_warning(
|
||||
"Unknown ACIO message %04x on h44b node, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ac_io_emu_h44b_cmd_send_version(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -93,8 +91,10 @@ static void ac_io_emu_h44b_cmd_send_version(
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x00;
|
||||
resp.cmd.version.revision = 0x02;
|
||||
memcpy(resp.cmd.version.product_code, "H44B",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"H44B",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||
|
||||
@@ -102,9 +102,9 @@ static void ac_io_emu_h44b_cmd_send_version(
|
||||
}
|
||||
|
||||
static void ac_io_emu_h44b_send_status(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
|
||||
@@ -15,12 +15,9 @@ struct ac_io_emu_h44b {
|
||||
void acioemu_h44b_init(void);
|
||||
|
||||
void ac_io_emu_h44b_init(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no);
|
||||
struct ac_io_emu_h44b *h44b, struct ac_io_emu *emu, uint8_t unit_no);
|
||||
|
||||
void ac_io_emu_h44b_dispatch_request(
|
||||
struct ac_io_emu_h44b *h44b,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_h44b *h44b, const struct ac_io_message *req);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,21 +8,17 @@
|
||||
#include "util/log.h"
|
||||
|
||||
static void ac_io_emu_hdxs_cmd_send_version(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_hdxs_send_empty(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_hdxs_send_status(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
|
||||
void ac_io_emu_hdxs_init(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
struct ac_io_emu *emu)
|
||||
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu)
|
||||
{
|
||||
log_assert(hdxs != NULL);
|
||||
log_assert(emu != NULL);
|
||||
@@ -31,8 +27,7 @@ void ac_io_emu_hdxs_init(
|
||||
}
|
||||
|
||||
void ac_io_emu_hdxs_dispatch_request(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
|
||||
{
|
||||
uint16_t cmd_code;
|
||||
|
||||
@@ -42,46 +37,45 @@ void ac_io_emu_hdxs_dispatch_request(
|
||||
cmd_code = ac_io_u16(req->cmd.code);
|
||||
|
||||
switch (cmd_code) {
|
||||
case AC_IO_CMD_GET_VERSION:
|
||||
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
|
||||
ac_io_emu_hdxs_cmd_send_version(hdxs, req);
|
||||
case AC_IO_CMD_GET_VERSION:
|
||||
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
|
||||
ac_io_emu_hdxs_cmd_send_version(hdxs, req);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_START_UP:
|
||||
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
|
||||
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
|
||||
case AC_IO_CMD_START_UP:
|
||||
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
|
||||
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_CLEAR:
|
||||
log_misc("AC_IO_CMD_CLEAR(%d)", req->addr);
|
||||
case AC_IO_CMD_CLEAR:
|
||||
log_misc("AC_IO_CMD_CLEAR(%d)", req->addr);
|
||||
|
||||
case 0x110:
|
||||
case 0x112:
|
||||
case 0x128:
|
||||
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
|
||||
case 0x110:
|
||||
case 0x112:
|
||||
case 0x128:
|
||||
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KEEPALIVE:
|
||||
ac_io_emu_hdxs_send_empty(hdxs, req);
|
||||
case AC_IO_CMD_KEEPALIVE:
|
||||
ac_io_emu_hdxs_send_empty(hdxs, req);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning(
|
||||
default:
|
||||
log_warning(
|
||||
"Unknown ACIO message %04x on HDXS node, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ac_io_emu_hdxs_cmd_send_version(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -94,8 +88,10 @@ static void ac_io_emu_hdxs_cmd_send_version(
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x06;
|
||||
resp.cmd.version.revision = 0x00;
|
||||
memcpy(resp.cmd.version.product_code, "HDXS",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"HDXS",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||
|
||||
@@ -103,8 +99,7 @@ static void ac_io_emu_hdxs_cmd_send_version(
|
||||
}
|
||||
|
||||
static void ac_io_emu_hdxs_send_empty(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -117,9 +112,9 @@ static void ac_io_emu_hdxs_send_empty(
|
||||
}
|
||||
|
||||
static void ac_io_emu_hdxs_send_status(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
|
||||
@@ -10,12 +10,9 @@ struct ac_io_emu_hdxs {
|
||||
// TODO ops vtbl
|
||||
};
|
||||
|
||||
void ac_io_emu_hdxs_init(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
struct ac_io_emu *emu);
|
||||
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu);
|
||||
|
||||
void ac_io_emu_hdxs_dispatch_request(
|
||||
struct ac_io_emu_hdxs *hdxs,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,39 +23,36 @@ enum ac_io_icca_subcmd {
|
||||
};
|
||||
|
||||
enum ac_io_icca_flag {
|
||||
AC_IO_ICCA_FLAG_FRONT_SENSOR = 0x10,
|
||||
AC_IO_ICCA_FLAG_REAR_SENSOR = 0x20,
|
||||
AC_IO_ICCA_FLAG_SOLENOID = 0x40
|
||||
AC_IO_ICCA_FLAG_FRONT_SENSOR = 0x10,
|
||||
AC_IO_ICCA_FLAG_REAR_SENSOR = 0x20,
|
||||
AC_IO_ICCA_FLAG_SOLENOID = 0x40
|
||||
};
|
||||
|
||||
enum ac_io_icca_status_code {
|
||||
AC_IO_ICCA_STATUS_FAULT = 0x00,
|
||||
AC_IO_ICCA_STATUS_IDLE = 0x01,
|
||||
AC_IO_ICCA_STATUS_GOT_UID = 0x02
|
||||
AC_IO_ICCA_STATUS_FAULT = 0x00,
|
||||
AC_IO_ICCA_STATUS_IDLE = 0x01,
|
||||
AC_IO_ICCA_STATUS_GOT_UID = 0x02,
|
||||
AC_IO_ICCA_STATUS_IDLE_NEW = 0x04
|
||||
};
|
||||
|
||||
static void ac_io_emu_icca_cmd_send_version(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_icca_send_state(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint64_t delay_us);
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint64_t delay_us);
|
||||
|
||||
static void ac_io_emu_icca_send_empty(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_icca_send_status(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
|
||||
void ac_io_emu_icca_init(
|
||||
struct ac_io_emu_icca *icca,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no)
|
||||
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no)
|
||||
{
|
||||
memset(icca, 0, sizeof(*icca));
|
||||
icca->emu = emu;
|
||||
@@ -65,8 +62,7 @@ void ac_io_emu_icca_init(
|
||||
}
|
||||
|
||||
void ac_io_emu_icca_dispatch_request(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
|
||||
{
|
||||
uint16_t cmd_code;
|
||||
uint64_t delay_us;
|
||||
@@ -131,10 +127,9 @@ void ac_io_emu_icca_dispatch_request(
|
||||
|
||||
break;
|
||||
|
||||
case AC_IO_ICCA_CMD_SET_SLOT_STATE:
|
||||
{
|
||||
struct ac_io_icca_misc* misc =
|
||||
(struct ac_io_icca_misc*) &req->cmd.raw;
|
||||
case AC_IO_ICCA_CMD_SET_SLOT_STATE: {
|
||||
struct ac_io_icca_misc *misc =
|
||||
(struct ac_io_icca_misc *) &req->cmd.raw;
|
||||
uint8_t cmd;
|
||||
|
||||
switch (misc->subcmd) {
|
||||
@@ -157,15 +152,19 @@ void ac_io_emu_icca_dispatch_request(
|
||||
|
||||
default:
|
||||
cmd = 0xFF;
|
||||
log_warning("Unhandled slot command %X, node %d",
|
||||
misc->subcmd, icca->unit_no);
|
||||
log_warning(
|
||||
"Unhandled slot command %X, node %d",
|
||||
misc->subcmd,
|
||||
icca->unit_no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd != 0xFF) {
|
||||
if (!eam_io_card_slot_cmd(icca->unit_no, cmd)) {
|
||||
log_warning("Eamio failed to handle slot cmd %d for node %d",
|
||||
cmd, icca->unit_no);
|
||||
log_warning(
|
||||
"Eamio failed to handle slot cmd %d for node %d",
|
||||
cmd,
|
||||
icca->unit_no);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,9 +175,11 @@ void ac_io_emu_icca_dispatch_request(
|
||||
}
|
||||
|
||||
case AC_IO_ICCA_CMD_POLL:
|
||||
delay_us = time_get_elapsed_us(time_get_counter() - icca->time_counter_last_poll);
|
||||
delay_us = time_get_elapsed_us(
|
||||
time_get_counter() - icca->time_counter_last_poll);
|
||||
|
||||
/* emulating delay implemented by hardware. do not delay messages that exceed a certain threshold. */
|
||||
/* emulating delay implemented by hardware. do not delay messages
|
||||
* that exceed a certain threshold. */
|
||||
if (delay_us > 16000) {
|
||||
delay_us = 0;
|
||||
}
|
||||
@@ -195,16 +196,17 @@ void ac_io_emu_icca_dispatch_request(
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("Unknown ACIO message %04x on ICCA node, addr=%d",
|
||||
cmd_code, req->addr);
|
||||
log_warning(
|
||||
"Unknown ACIO message %04x on ICCA node, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ac_io_emu_icca_cmd_send_version(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -217,8 +219,10 @@ static void ac_io_emu_icca_cmd_send_version(
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x06;
|
||||
resp.cmd.version.revision = 0x00;
|
||||
memcpy(resp.cmd.version.product_code, "ICCA",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"ICCA",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||
|
||||
@@ -226,8 +230,7 @@ static void ac_io_emu_icca_cmd_send_version(
|
||||
}
|
||||
|
||||
static void ac_io_emu_icca_send_empty(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -240,9 +243,9 @@ static void ac_io_emu_icca_send_empty(
|
||||
}
|
||||
|
||||
static void ac_io_emu_icca_send_status(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -256,9 +259,9 @@ static void ac_io_emu_icca_send_status(
|
||||
}
|
||||
|
||||
static void ac_io_emu_icca_send_state(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint64_t delay_us)
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req,
|
||||
uint64_t delay_us)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
struct ac_io_icca_state *body;
|
||||
@@ -277,25 +280,22 @@ static void ac_io_emu_icca_send_state(
|
||||
|
||||
keypad = eam_io_get_keypad_state(icca->unit_no);
|
||||
sensor_state = eam_io_get_sensor_state(icca->unit_no);
|
||||
|
||||
|
||||
keypad_rise = keypad & (icca->last_keypad ^ keypad);
|
||||
card_full_insert = sensor_state & (1 << EAM_IO_SENSOR_FRONT) &&
|
||||
sensor_state & (1 << EAM_IO_SENSOR_BACK);
|
||||
|
||||
if (sensor_state != icca->last_sensor) {
|
||||
|
||||
if (card_full_insert) {
|
||||
|
||||
if (!eam_io_card_slot_cmd(icca->unit_no,
|
||||
EAM_IO_CARD_SLOT_CMD_READ)) {
|
||||
log_warning("EAM_IO_CARD_SLOT_CMD_READ to unit %d failed",
|
||||
if (!eam_io_card_slot_cmd(
|
||||
icca->unit_no, EAM_IO_CARD_SLOT_CMD_READ)) {
|
||||
log_warning(
|
||||
"EAM_IO_CARD_SLOT_CMD_READ to unit %d failed",
|
||||
icca->unit_no);
|
||||
}
|
||||
|
||||
icca->card_result = eam_io_read_card(
|
||||
icca->unit_no,
|
||||
icca->uid,
|
||||
sizeof(icca->uid));
|
||||
icca->card_result =
|
||||
eam_io_read_card(icca->unit_no, icca->uid, sizeof(icca->uid));
|
||||
|
||||
// fault if sensor says to read but we got no card
|
||||
icca->fault = (icca->card_result == EAM_IO_CARD_NONE);
|
||||
@@ -319,7 +319,11 @@ static void ac_io_emu_icca_send_state(
|
||||
} else if (card_full_insert) {
|
||||
body->status_code = AC_IO_ICCA_STATUS_GOT_UID;
|
||||
} else {
|
||||
body->status_code = AC_IO_ICCA_STATUS_IDLE;
|
||||
if (icca->detected_new_reader) {
|
||||
body->status_code = AC_IO_ICCA_STATUS_IDLE_NEW;
|
||||
} else {
|
||||
body->status_code = AC_IO_ICCA_STATUS_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
body->sensor_state = 0;
|
||||
@@ -338,8 +342,8 @@ static void ac_io_emu_icca_send_state(
|
||||
|
||||
memcpy(body->uid, icca->uid, sizeof(body->uid));
|
||||
body->card_type = 0;
|
||||
if (body->status_code == AC_IO_ICCA_STATUS_GOT_UID){
|
||||
if (icca->detected_new_reader){
|
||||
if (body->status_code == AC_IO_ICCA_STATUS_GOT_UID) {
|
||||
if (icca->detected_new_reader) {
|
||||
// sensor_state actually refers to cardtype for wavepass readers
|
||||
// EAM_IO_CARD_ISO15696 = 1 -> 0
|
||||
// EAM_IO_CARD_FELICA = 2 -> 1
|
||||
@@ -349,7 +353,6 @@ static void ac_io_emu_icca_send_state(
|
||||
}
|
||||
|
||||
if (keypad_rise) {
|
||||
|
||||
if (icca->key_events[0]) {
|
||||
event = (icca->key_events[0] + 0x10) & 0xF0;
|
||||
} else {
|
||||
@@ -365,7 +368,8 @@ static void ac_io_emu_icca_send_state(
|
||||
|
||||
// this doesn't seem to be an error code. If this is not set to 0x03
|
||||
// on slotted readers (only?), the game throws an unknown status error
|
||||
if (icca->keypad_started) {
|
||||
// and on SDVX4 it hangs on the thank you screen
|
||||
if (icca->keypad_started || icca->detected_new_reader) {
|
||||
body->keypad_started = 0x03;
|
||||
} else {
|
||||
body->keypad_started = 0x00;
|
||||
@@ -382,4 +386,3 @@ static void ac_io_emu_icca_send_state(
|
||||
|
||||
ac_io_emu_response_push(icca->emu, &resp, delay_us);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,9 @@ struct ac_io_emu_icca {
|
||||
};
|
||||
|
||||
void ac_io_emu_icca_init(
|
||||
struct ac_io_emu_icca *icca,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no);
|
||||
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no);
|
||||
|
||||
void ac_io_emu_icca_dispatch_request(
|
||||
struct ac_io_emu_icca *icca,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,26 +14,21 @@
|
||||
#include "bemanitools/eamio.h"
|
||||
|
||||
static void ac_io_emu_iccb_cmd_send_version(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_iccb_send_state(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_iccb_send_empty(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
|
||||
|
||||
static void ac_io_emu_iccb_send_status(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status);
|
||||
|
||||
void ac_io_emu_iccb_init(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no)
|
||||
struct ac_io_emu_iccb *iccb, struct ac_io_emu *emu, uint8_t unit_no)
|
||||
{
|
||||
memset(iccb, 0, sizeof(*iccb));
|
||||
iccb->emu = emu;
|
||||
@@ -41,8 +36,7 @@ void ac_io_emu_iccb_init(
|
||||
}
|
||||
|
||||
void ac_io_emu_iccb_dispatch_request(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
||||
{
|
||||
uint16_t cmd_code;
|
||||
|
||||
@@ -104,16 +98,17 @@ void ac_io_emu_iccb_dispatch_request(
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("Unknown ACIO message %04x on ICCB node, addr=%d",
|
||||
cmd_code, req->addr);
|
||||
log_warning(
|
||||
"Unknown ACIO message %04x on ICCB node, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ac_io_emu_iccb_cmd_send_version(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -126,8 +121,10 @@ static void ac_io_emu_iccb_cmd_send_version(
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x05;
|
||||
resp.cmd.version.revision = 0x01;
|
||||
memcpy(resp.cmd.version.product_code, "ICCB",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"ICCB",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||
|
||||
@@ -135,8 +132,7 @@ static void ac_io_emu_iccb_cmd_send_version(
|
||||
}
|
||||
|
||||
static void ac_io_emu_iccb_send_empty(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -149,9 +145,9 @@ static void ac_io_emu_iccb_send_empty(
|
||||
}
|
||||
|
||||
static void ac_io_emu_iccb_send_status(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req,
|
||||
uint8_t status)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
|
||||
@@ -165,8 +161,7 @@ static void ac_io_emu_iccb_send_status(
|
||||
}
|
||||
|
||||
static void ac_io_emu_iccb_send_state(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req)
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
struct ac_io_iccb_state *body;
|
||||
@@ -178,10 +173,8 @@ static void ac_io_emu_iccb_send_state(
|
||||
|
||||
if (sensor != iccb->last_sensor) {
|
||||
if (sensor) {
|
||||
iccb->card_result = eam_io_read_card(
|
||||
iccb->unit_no,
|
||||
iccb->uid,
|
||||
sizeof(iccb->uid));
|
||||
iccb->card_result =
|
||||
eam_io_read_card(iccb->unit_no, iccb->uid, sizeof(iccb->uid));
|
||||
|
||||
// fault if sensor says to read but we got no card
|
||||
iccb->fault = (iccb->card_result == EAM_IO_CARD_NONE);
|
||||
@@ -224,4 +217,3 @@ static void ac_io_emu_iccb_send_state(
|
||||
|
||||
ac_io_emu_response_push(iccb->emu, &resp, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,9 @@ struct ac_io_emu_iccb {
|
||||
};
|
||||
|
||||
void ac_io_emu_iccb_init(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
struct ac_io_emu *emu,
|
||||
uint8_t unit_no);
|
||||
struct ac_io_emu_iccb *iccb, struct ac_io_emu *emu, uint8_t unit_no);
|
||||
|
||||
void ac_io_emu_iccb_dispatch_request(
|
||||
struct ac_io_emu_iccb *iccb,
|
||||
const struct ac_io_message *req);
|
||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,11 +13,10 @@
|
||||
#include "util/mem.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
|
||||
uint64_t delay_us);
|
||||
static struct ac_io_in_queued *
|
||||
ac_io_in_queued_alloc(struct ac_io_in *in, uint64_t delay_us);
|
||||
static void ac_io_in_queued_populate(
|
||||
struct ac_io_in_queued *iq,
|
||||
const struct ac_io_message *msg);
|
||||
struct ac_io_in_queued *iq, const struct ac_io_message *msg);
|
||||
static void ac_io_in_queued_putc(struct ac_io_in_queued *iq, uint8_t b);
|
||||
|
||||
static bool ac_io_out_supply_byte(struct ac_io_out *out, uint8_t b);
|
||||
@@ -30,8 +29,8 @@ static bool ac_io_out_reject_message(struct ac_io_out *out);
|
||||
|
||||
static bool ac_io_enable_legacy_mode = false;
|
||||
|
||||
static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
|
||||
uint64_t delay_us)
|
||||
static struct ac_io_in_queued *
|
||||
ac_io_in_queued_alloc(struct ac_io_in *in, uint64_t delay_us)
|
||||
{
|
||||
struct ac_io_in_queued *iq;
|
||||
|
||||
@@ -51,8 +50,7 @@ static struct ac_io_in_queued *ac_io_in_queued_alloc(struct ac_io_in *in,
|
||||
}
|
||||
|
||||
static void ac_io_in_queued_populate(
|
||||
struct ac_io_in_queued *iq,
|
||||
const struct ac_io_message *msg)
|
||||
struct ac_io_in_queued *iq, const struct ac_io_message *msg)
|
||||
{
|
||||
uint8_t checksum;
|
||||
const uint8_t *src;
|
||||
@@ -68,7 +66,7 @@ static void ac_io_in_queued_populate(
|
||||
src = (const uint8_t *) msg;
|
||||
checksum = 0;
|
||||
|
||||
for (i = 0 ; i < nbytes ; i++) {
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
ac_io_in_queued_putc(iq, src[i]);
|
||||
checksum += src[i];
|
||||
}
|
||||
@@ -97,8 +95,8 @@ void ac_io_in_init(struct ac_io_in *in)
|
||||
list_init(&in->queue);
|
||||
}
|
||||
|
||||
void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
|
||||
uint64_t delay_us)
|
||||
void ac_io_in_supply(
|
||||
struct ac_io_in *in, const struct ac_io_message *msg, uint64_t delay_us)
|
||||
{
|
||||
struct ac_io_in_queued *dest;
|
||||
|
||||
@@ -113,10 +111,7 @@ void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
|
||||
}
|
||||
|
||||
void ac_io_in_supply_thunk(
|
||||
struct ac_io_in *in,
|
||||
ac_io_in_thunk_t thunk,
|
||||
void *ctx,
|
||||
uint64_t delay_us)
|
||||
struct ac_io_in *in, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay_us)
|
||||
{
|
||||
struct ac_io_in_queued *dest;
|
||||
|
||||
@@ -177,7 +172,7 @@ void ac_io_in_drain(struct ac_io_in *in, struct iobuf *dest)
|
||||
if (ac_io_enable_legacy_mode) {
|
||||
break;
|
||||
}
|
||||
} while (nmoved > 0);
|
||||
} while (nmoved > 0);
|
||||
}
|
||||
|
||||
bool ac_io_in_is_msg_pending(const struct ac_io_in *in)
|
||||
@@ -209,7 +204,6 @@ static bool ac_io_out_supply_byte(struct ac_io_out *out, uint8_t b)
|
||||
if (out->in_frame) {
|
||||
return ac_io_out_supply_frame_byte(out, b);
|
||||
} else {
|
||||
|
||||
if (b == AC_IO_SOF) {
|
||||
out->in_frame = true;
|
||||
} else if (b == AC_IO_ESCAPE) {
|
||||
@@ -235,7 +229,6 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
|
||||
|
||||
return true;
|
||||
} else if (b == AC_IO_SOF) {
|
||||
|
||||
if (out->pos == 0) {
|
||||
/* Got autobaud/empty message */
|
||||
out->have_message = true;
|
||||
@@ -247,7 +240,6 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Payload byte */
|
||||
@@ -257,13 +249,11 @@ static bool ac_io_out_supply_frame_byte(struct ac_io_out *out, uint8_t b)
|
||||
/* Handle contextually-implied end-of-packet events */
|
||||
|
||||
if (out->pos > offsetof(struct ac_io_message, addr)) {
|
||||
|
||||
if (out->msg.addr == AC_IO_BROADCAST) {
|
||||
return ac_io_out_detect_broadcast_eof(out);
|
||||
} else {
|
||||
return ac_io_out_detect_command_eof(out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -274,9 +264,8 @@ static bool ac_io_out_detect_broadcast_eof(struct ac_io_out *out)
|
||||
size_t end;
|
||||
|
||||
if (out->pos > offsetof(struct ac_io_message, bcast.nbytes)) {
|
||||
end = offsetof(struct ac_io_message,bcast.raw)
|
||||
+ out->msg.bcast.nbytes
|
||||
+ 1;
|
||||
end = offsetof(struct ac_io_message, bcast.raw) +
|
||||
out->msg.bcast.nbytes + 1;
|
||||
|
||||
if (out->pos == end) {
|
||||
return ac_io_out_check_sum(out);
|
||||
@@ -291,9 +280,7 @@ static bool ac_io_out_detect_command_eof(struct ac_io_out *out)
|
||||
size_t end;
|
||||
|
||||
if (out->pos > offsetof(struct ac_io_message, cmd.nbytes)) {
|
||||
end = offsetof(struct ac_io_message, cmd.raw)
|
||||
+ out->msg.cmd.nbytes
|
||||
+ 1;
|
||||
end = offsetof(struct ac_io_message, cmd.raw) + out->msg.cmd.nbytes + 1;
|
||||
|
||||
if (out->pos == end) {
|
||||
return ac_io_out_check_sum(out);
|
||||
@@ -310,15 +297,17 @@ static bool ac_io_out_check_sum(struct ac_io_out *out)
|
||||
|
||||
checksum = 0;
|
||||
|
||||
for (i = 0 ; i < out->pos - 1 ; i++) {
|
||||
for (i = 0; i < out->pos - 1; i++) {
|
||||
checksum += out->bytes[i];
|
||||
}
|
||||
|
||||
if (checksum == out->bytes[out->pos - 1]) {
|
||||
return ac_io_out_accept_message(out);
|
||||
} else {
|
||||
log_warning("Checksum bad: expected %02x got %02x",
|
||||
checksum, out->bytes[out->pos - 1]);
|
||||
log_warning(
|
||||
"Checksum bad: expected %02x got %02x",
|
||||
checksum,
|
||||
out->bytes[out->pos - 1]);
|
||||
|
||||
return ac_io_out_reject_message(out);
|
||||
}
|
||||
@@ -363,4 +352,3 @@ void ac_io_out_consume_message(struct ac_io_out *out)
|
||||
out->have_message = false;
|
||||
out->escape = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,13 +47,10 @@ struct ac_io_out {
|
||||
void ac_io_legacy_mode(void);
|
||||
|
||||
void ac_io_in_init(struct ac_io_in *in);
|
||||
void ac_io_in_supply(struct ac_io_in *in, const struct ac_io_message *msg,
|
||||
uint64_t delay);
|
||||
void ac_io_in_supply(
|
||||
struct ac_io_in *in, const struct ac_io_message *msg, uint64_t delay);
|
||||
void ac_io_in_supply_thunk(
|
||||
struct ac_io_in *in,
|
||||
ac_io_in_thunk_t thunk,
|
||||
void *ctx,
|
||||
uint64_t delay);
|
||||
struct ac_io_in *in, ac_io_in_thunk_t thunk, void *ctx, uint64_t delay);
|
||||
void ac_io_in_drain(struct ac_io_in *in, struct iobuf *dest);
|
||||
bool ac_io_in_is_msg_pending(const struct ac_io_in *in);
|
||||
|
||||
|
||||
@@ -6,11 +6,10 @@ static const uint8_t aciotest_handler_max = 16;
|
||||
/**
|
||||
* Handler interface for an ACIO device.
|
||||
*/
|
||||
struct aciotest_handler_node_handler
|
||||
{
|
||||
void* ctx;
|
||||
bool (*init)(uint8_t node_id, void** ctx);
|
||||
bool (*update)(uint8_t node_id, void* ctx);
|
||||
struct aciotest_handler_node_handler {
|
||||
void *ctx;
|
||||
bool (*init)(uint8_t node_id, void **ctx);
|
||||
bool (*update)(uint8_t node_id, void *ctx);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,28 +1,28 @@
|
||||
#include "aciotest/icca.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "aciodrv/icca.h"
|
||||
|
||||
bool aciotest_icca_handler_init(uint8_t node_id, void** ctx)
|
||||
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx)
|
||||
{
|
||||
*ctx = malloc(sizeof(uint32_t));
|
||||
*((uint32_t*) *ctx) = 0;
|
||||
*((uint32_t *) *ctx) = 0;
|
||||
|
||||
return aciodrv_icca_init(node_id);
|
||||
}
|
||||
|
||||
bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
|
||||
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
|
||||
{
|
||||
if (*((uint32_t*) ctx) == 0) {
|
||||
*((uint32_t*) ctx) = 1;
|
||||
if (*((uint32_t *) ctx) == 0) {
|
||||
*((uint32_t *) ctx) = 1;
|
||||
|
||||
/* eject cards that were left in the reader */
|
||||
if (!aciodrv_icca_set_state(node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
||||
if (!aciodrv_icca_set_state(
|
||||
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct ac_io_icca_state state;
|
||||
@@ -31,7 +31,8 @@ bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(">>> ICCA %d:\n"
|
||||
printf(
|
||||
">>> ICCA %d:\n"
|
||||
"status_code: %d\n"
|
||||
"sensor_state: %d\n"
|
||||
"keypad_started: %d\n"
|
||||
@@ -40,43 +41,51 @@ bool aciotest_icca_handler_update(uint8_t node_id, void* ctx)
|
||||
"key_state: %04X\n"
|
||||
"key_events[0]: %02X\n"
|
||||
"key_events[1]: %02X\n",
|
||||
node_id, state.status_code, state.sensor_state, state.keypad_started,
|
||||
state.card_type,
|
||||
state.uid[0], state.uid[1], state.uid[2], state.uid[3],
|
||||
state.uid[4], state.uid[5], state.uid[6], state.uid[7],
|
||||
state.key_state, state.key_events[0], state.key_events[1]);
|
||||
node_id,
|
||||
state.status_code,
|
||||
state.sensor_state,
|
||||
state.keypad_started,
|
||||
state.card_type,
|
||||
state.uid[0],
|
||||
state.uid[1],
|
||||
state.uid[2],
|
||||
state.uid[3],
|
||||
state.uid[4],
|
||||
state.uid[5],
|
||||
state.uid[6],
|
||||
state.uid[7],
|
||||
state.key_state,
|
||||
state.key_events[0],
|
||||
state.key_events[1]);
|
||||
|
||||
/* eject card with "empty" key */
|
||||
if (state.key_state & AC_IO_ICCA_KEYPAD_MASK_EMPTY) {
|
||||
|
||||
if (!aciodrv_icca_set_state(node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
||||
if (!aciodrv_icca_set_state(
|
||||
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* allow new card to be inserted when slot is clear */
|
||||
if ( !(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
|
||||
!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
|
||||
|
||||
if (!aciodrv_icca_set_state(node_id, AC_IO_ICCA_SLOT_STATE_OPEN, NULL)) {
|
||||
if (!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
|
||||
!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
|
||||
if (!aciodrv_icca_set_state(
|
||||
node_id, AC_IO_ICCA_SLOT_STATE_OPEN, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* lock the card when fully inserted */
|
||||
if ( (state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
|
||||
(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
|
||||
|
||||
if (!aciodrv_icca_set_state(node_id, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL)) {
|
||||
if ((state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
|
||||
(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
|
||||
if (!aciodrv_icca_set_state(
|
||||
node_id, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aciodrv_icca_read_card(node_id, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef ACIOTEST_ICCA_H
|
||||
#define ACIOTEST_ICCA_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool aciotest_icca_handler_init(uint8_t node_id, void** ctx);
|
||||
bool aciotest_icca_handler_update(uint8_t node_id, void* ctx);
|
||||
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx);
|
||||
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx);
|
||||
|
||||
#endif
|
||||
@@ -1,22 +1,22 @@
|
||||
#include "aciotest/kfca.h"
|
||||
#include "aciotest/kfca.h"
|
||||
|
||||
#include "acio/acio.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aciodrv/kfca.h"
|
||||
|
||||
bool aciotest_kfca_handler_init(uint8_t node_id, void** ctx)
|
||||
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx)
|
||||
{
|
||||
*ctx = malloc(sizeof(uint32_t));
|
||||
*((uint32_t*) *ctx) = 0;
|
||||
*((uint32_t *) *ctx) = 0;
|
||||
|
||||
return aciodrv_kfca_init(node_id);
|
||||
}
|
||||
|
||||
bool aciotest_kfca_handler_update(uint8_t node_id, void* ctx)
|
||||
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
|
||||
{
|
||||
struct ac_io_kfca_poll_in pin;
|
||||
struct ac_io_kfca_poll_out pout;
|
||||
@@ -38,28 +38,29 @@ bool aciotest_kfca_handler_update(uint8_t node_id, void* ctx)
|
||||
pin.gpio[0] = ac_io_u16(pin.gpio[0]);
|
||||
pin.gpio[1] = ac_io_u16(pin.gpio[1]);
|
||||
|
||||
printf(">>> KFCA %d: GPIO ON %d\n"
|
||||
printf(
|
||||
">>> KFCA %d: GPIO ON %d\n"
|
||||
"BTN A B C D: %d %d %d %d\n"
|
||||
"FX-L R: %d %d\n"
|
||||
"VOL L: %d\n"
|
||||
"VOL R: %d\n"
|
||||
"START COIN TEST SERV REC HP: %d %d %d %d %d %d\n",
|
||||
node_id, gpio_test_pin,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_A,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_B,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_C,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_D,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_L,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_R,
|
||||
(pin.adc[0] >> 6) & 0x3FF,
|
||||
(pin.adc[1] >> 6) & 0x3FF,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_START,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_COIN,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_TEST,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_SERVICE,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_RECORDER,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_HEADPHONE
|
||||
);
|
||||
node_id,
|
||||
gpio_test_pin,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_A,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_B,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_C,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_D,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_L,
|
||||
pin.gpio[1] & AC_IO_KFCA_IN_GPIO_1_FX_R,
|
||||
(pin.adc[0] >> 6) & 0x3FF,
|
||||
(pin.adc[1] >> 6) & 0x3FF,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_START,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_COIN,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_TEST,
|
||||
(pin.gpio_sys) & AC_IO_KFCA_IN_GPIO_SYS_SERVICE,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_RECORDER,
|
||||
pin.gpio[0] & AC_IO_KFCA_IN_GPIO_0_HEADPHONE);
|
||||
|
||||
++gpio_test_counter;
|
||||
if (gpio_test_counter >= 4) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef ACIOTEST_KFCA_H
|
||||
#define ACIOTEST_KFCA_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool aciotest_kfca_handler_init(uint8_t node_id, void** ctx);
|
||||
bool aciotest_kfca_handler_update(uint8_t node_id, void* ctx);
|
||||
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx);
|
||||
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -17,20 +17,18 @@ static uint8_t aciotest_cnt = 0;
|
||||
/**
|
||||
* Enumerate supported ACIO nodes based on their product id.
|
||||
*/
|
||||
static bool aciotest_assign_handler(char product[4],
|
||||
struct aciotest_handler_node_handler* handler)
|
||||
static bool aciotest_assign_handler(
|
||||
char product[4], struct aciotest_handler_node_handler *handler)
|
||||
{
|
||||
if (!memcmp(product, "ICCA", 4)
|
||||
|| !memcmp(product, "ICCB", 4)
|
||||
|| !memcmp(product, "ICCC", 4)
|
||||
){
|
||||
if (!memcmp(product, "ICCA", 4) || !memcmp(product, "ICCB", 4) ||
|
||||
!memcmp(product, "ICCC", 4)) {
|
||||
handler->init = aciotest_icca_handler_init;
|
||||
handler->update = aciotest_icca_handler_update;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!memcmp(product, "KFCA", 4)){
|
||||
if (!memcmp(product, "KFCA", 4)) {
|
||||
handler->init = aciotest_kfca_handler_init;
|
||||
handler->update = aciotest_kfca_handler_update;
|
||||
|
||||
@@ -43,14 +41,17 @@ static bool aciotest_assign_handler(char product[4],
|
||||
/**
|
||||
* Tool to test real ACIO hardware.
|
||||
*/
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
printf(
|
||||
"aciotest, build "__DATE__ " " __TIME__ "\n"
|
||||
"aciotest, build "__DATE__
|
||||
" " __TIME__
|
||||
"\n"
|
||||
"Usage: %s <com port str> <baud rate>\n"
|
||||
"Example for two slotted readers: %s COM1 57600\n",
|
||||
argv[0], argv[0]);
|
||||
argv[0],
|
||||
argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -67,33 +68,40 @@ int main(int argc, char** argv)
|
||||
printf("Enumerated %d nodes\n", node_count);
|
||||
|
||||
struct aciotest_handler_node_handler handler[aciotest_handler_max];
|
||||
memset(&handler, 0,
|
||||
memset(
|
||||
&handler,
|
||||
0,
|
||||
sizeof(struct aciotest_handler_node_handler) * aciotest_handler_max);
|
||||
|
||||
for (uint8_t i = 0; i < node_count; i++) {
|
||||
char product[4];
|
||||
aciodrv_device_get_node_product_ident(i, product);
|
||||
printf("> %d: %c%c%c%c\n", i + 1,
|
||||
product[0], product[1], product[2], product[3]);
|
||||
printf(
|
||||
"> %d: %c%c%c%c\n",
|
||||
i + 1,
|
||||
product[0],
|
||||
product[1],
|
||||
product[2],
|
||||
product[3]);
|
||||
|
||||
if (!aciotest_assign_handler(product, &handler[i])) {
|
||||
printf("ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
|
||||
product[0], product[1], product[2], product[3], i);
|
||||
printf(
|
||||
"ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
|
||||
product[0],
|
||||
product[1],
|
||||
product[2],
|
||||
product[3],
|
||||
i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
||||
|
||||
if (handler[i].init != NULL) {
|
||||
|
||||
if (!handler[i].init(i, &handler[i].ctx)) {
|
||||
printf("ERROR: Initializing node %d failed\n", i);
|
||||
handler[i].update = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf(">>> Initializing done, press enter to start update loop <<<\n");
|
||||
@@ -107,17 +115,13 @@ int main(int argc, char** argv)
|
||||
printf("%d\n", aciotest_cnt++);
|
||||
|
||||
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
||||
|
||||
if (handler[i].update != NULL) {
|
||||
|
||||
if (!handler[i].update(i, handler[i].ctx)) {
|
||||
printf("ERROR: Updating node %d, removed from loop\n", i);
|
||||
handler[i].update = NULL;
|
||||
Sleep(5000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* avoid cpu banging */
|
||||
|
||||
@@ -18,8 +18,11 @@ enum bst_io_in_gpio_sys_bit {
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void bst_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void bst_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your BST IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -29,8 +32,10 @@ void bst_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool bst_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool bst_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your SDVX IO emulation DLL */
|
||||
|
||||
|
||||
@@ -62,8 +62,11 @@ enum extio_light_bit {
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void ddr_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void ddr_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your DDR IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -73,8 +76,10 @@ void ddr_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool ddr_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool ddr_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
uint32_t ddr_io_read_pad(void);
|
||||
void ddr_io_set_lights_extio(uint32_t extio_lights);
|
||||
|
||||
@@ -15,20 +15,20 @@
|
||||
return from eam_io_get_keypad_state(). */
|
||||
|
||||
enum eam_io_keypad_scan_code {
|
||||
EAM_IO_KEYPAD_0 = 0,
|
||||
EAM_IO_KEYPAD_1 = 1,
|
||||
EAM_IO_KEYPAD_4 = 2,
|
||||
EAM_IO_KEYPAD_7 = 3,
|
||||
EAM_IO_KEYPAD_00 = 4,
|
||||
EAM_IO_KEYPAD_2 = 5,
|
||||
EAM_IO_KEYPAD_5 = 6,
|
||||
EAM_IO_KEYPAD_8 = 7,
|
||||
EAM_IO_KEYPAD_DECIMAL = 8,
|
||||
EAM_IO_KEYPAD_3 = 9,
|
||||
EAM_IO_KEYPAD_6 = 10,
|
||||
EAM_IO_KEYPAD_9 = 11,
|
||||
EAM_IO_KEYPAD_0 = 0,
|
||||
EAM_IO_KEYPAD_1 = 1,
|
||||
EAM_IO_KEYPAD_4 = 2,
|
||||
EAM_IO_KEYPAD_7 = 3,
|
||||
EAM_IO_KEYPAD_00 = 4,
|
||||
EAM_IO_KEYPAD_2 = 5,
|
||||
EAM_IO_KEYPAD_5 = 6,
|
||||
EAM_IO_KEYPAD_8 = 7,
|
||||
EAM_IO_KEYPAD_DECIMAL = 8,
|
||||
EAM_IO_KEYPAD_3 = 9,
|
||||
EAM_IO_KEYPAD_6 = 10,
|
||||
EAM_IO_KEYPAD_9 = 11,
|
||||
|
||||
EAM_IO_KEYPAD_COUNT = 12, /* Not an actual scan code */
|
||||
EAM_IO_KEYPAD_COUNT = 12, /* Not an actual scan code */
|
||||
};
|
||||
|
||||
/* Emulating the sensors of a slotted card reader. The reader has one
|
||||
@@ -70,8 +70,11 @@ struct eam_io_config_api;
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void eam_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void eam_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your card reader emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -81,8 +84,10 @@ void eam_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool eam_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool eam_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your card reader emulation DLL. */
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Bemanitools is compiled with GCC (MinGW, specifically) as of version 5 */
|
||||
#define LOG_CHECK_FMT __attribute__(( format(printf, 2, 3) ))
|
||||
#define LOG_CHECK_FMT __attribute__((format(printf, 2, 3)))
|
||||
#else
|
||||
/* Compile it out for MSVC plebs */
|
||||
#define LOG_CHECK_FMT
|
||||
@@ -28,7 +28,7 @@
|
||||
proprietary extensions), so don't use any overly exotic formats. */
|
||||
|
||||
typedef void (*log_formatter_t)(const char *module, const char *fmt, ...)
|
||||
LOG_CHECK_FMT;
|
||||
LOG_CHECK_FMT;
|
||||
|
||||
/* An API for spawning threads. This API is defined by libavs, although
|
||||
Bemanitools itself may supply compatible implementations of these functions
|
||||
@@ -39,8 +39,8 @@ typedef void (*log_formatter_t)(const char *module, const char *fmt, ...)
|
||||
this restriction will cause the process to crash. This is a limitation of
|
||||
libavs itself, not Bemanitools. */
|
||||
|
||||
typedef int (*thread_create_t)(int (*proc)(void *), void *ctx,
|
||||
uint32_t stack_sz, unsigned int priority);
|
||||
typedef int (*thread_create_t)(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority);
|
||||
typedef void (*thread_join_t)(int thread_id, int *result);
|
||||
typedef void (*thread_destroy_t)(int thread_id);
|
||||
|
||||
|
||||
@@ -44,16 +44,16 @@ enum iidx_io_key_bit {
|
||||
/* Bit mapping for the P1 and P2 deck lights */
|
||||
|
||||
enum iidx_io_deck_light {
|
||||
IIDX_IO_DECK_LIGHT_P1_1 = 0,
|
||||
IIDX_IO_DECK_LIGHT_P1_2 = 1,
|
||||
IIDX_IO_DECK_LIGHT_P1_3 = 2,
|
||||
IIDX_IO_DECK_LIGHT_P1_4 = 3,
|
||||
IIDX_IO_DECK_LIGHT_P1_5 = 4,
|
||||
IIDX_IO_DECK_LIGHT_P1_6 = 5,
|
||||
IIDX_IO_DECK_LIGHT_P1_7 = 6,
|
||||
IIDX_IO_DECK_LIGHT_P1_1 = 0,
|
||||
IIDX_IO_DECK_LIGHT_P1_2 = 1,
|
||||
IIDX_IO_DECK_LIGHT_P1_3 = 2,
|
||||
IIDX_IO_DECK_LIGHT_P1_4 = 3,
|
||||
IIDX_IO_DECK_LIGHT_P1_5 = 4,
|
||||
IIDX_IO_DECK_LIGHT_P1_6 = 5,
|
||||
IIDX_IO_DECK_LIGHT_P1_7 = 6,
|
||||
|
||||
IIDX_IO_DECK_LIGHT_P2_1 = 8,
|
||||
IIDX_IO_DECK_LIGHT_P2_2 = 9,
|
||||
IIDX_IO_DECK_LIGHT_P2_1 = 8,
|
||||
IIDX_IO_DECK_LIGHT_P2_2 = 9,
|
||||
IIDX_IO_DECK_LIGHT_P2_3 = 10,
|
||||
IIDX_IO_DECK_LIGHT_P2_4 = 11,
|
||||
IIDX_IO_DECK_LIGHT_P2_5 = 12,
|
||||
@@ -66,16 +66,19 @@ enum iidx_io_deck_light {
|
||||
enum iidx_io_panel_light {
|
||||
IIDX_IO_PANEL_LIGHT_P1_START = 0,
|
||||
IIDX_IO_PANEL_LIGHT_P2_START = 1,
|
||||
IIDX_IO_PANEL_LIGHT_VEFX = 2,
|
||||
IIDX_IO_PANEL_LIGHT_EFFECT = 3,
|
||||
IIDX_IO_PANEL_LIGHT_VEFX = 2,
|
||||
IIDX_IO_PANEL_LIGHT_EFFECT = 3,
|
||||
};
|
||||
|
||||
/* The first function that will be called on your DLL. You will be supplied
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void iidx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void iidx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your IIDX IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -85,8 +88,10 @@ void iidx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool iidx_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool iidx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your IIDX IO emulation DLL */
|
||||
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
|
||||
This is the only function that can safely be called before input_init(). */
|
||||
|
||||
void input_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void input_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize the generic input subsystem. You must pass on the thread
|
||||
management functions that have been supplied to your DLL.
|
||||
@@ -35,8 +38,10 @@ void input_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
game_type parameter, otherwise you will not receive any input, and any
|
||||
attempts to set a light output level will have no effect. */
|
||||
|
||||
void input_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
void input_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down the generic input subsystem. After calling this function, no
|
||||
geninput functions other than input_set_loggers() or input_init() may be
|
||||
|
||||
@@ -50,8 +50,11 @@ enum jb_io_rgb_led {
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void jb_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void jb_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your JB IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -61,8 +64,10 @@ void jb_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool jb_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool jb_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your JB IO emulation DLL */
|
||||
|
||||
@@ -78,6 +83,7 @@ uint8_t jb_io_get_sys_inputs(void);
|
||||
|
||||
uint16_t jb_io_get_panel_inputs(void);
|
||||
|
||||
void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b);
|
||||
void jb_io_set_rgb_led(
|
||||
enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,8 +43,11 @@ enum sdvx_io_out_gpio_bit {
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void sdvx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void sdvx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your SDVX IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -54,8 +57,10 @@ void sdvx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool sdvx_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool sdvx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your SDVX IO emulation DLL */
|
||||
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
void vefx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal);
|
||||
void vefx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal);
|
||||
|
||||
/* Initialize your IIDX IO emulation DLL. Thread management functions are
|
||||
provided to you; you must use these functions to create your own threads if
|
||||
@@ -23,8 +26,10 @@ void vefx_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
|
||||
See glue.h and geninput.h for further details. */
|
||||
|
||||
bool vefx_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
bool vefx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy);
|
||||
|
||||
/* Shut down your IIDX IO emulation DLL */
|
||||
|
||||
@@ -40,7 +45,7 @@ void vefx_io_fini(void);
|
||||
|
||||
See iidxio.c for mappings. */
|
||||
|
||||
bool vefx_io_recv(uint64_t* ppad);
|
||||
bool vefx_io_recv(uint64_t *ppad);
|
||||
|
||||
/* Get slider position, where 0 is the bottom position and 15 is the topmost
|
||||
position. slider_no is a number between 0 (leftmost) and 4 (rightmost). */
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// clang-format off
|
||||
// Don't format because the order is important here
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntdef.h>
|
||||
#include <devioctl.h>
|
||||
#include <ntddser.h>
|
||||
// clang-format on
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -20,11 +22,11 @@
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/iobuf.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/array.h"
|
||||
|
||||
static struct array bio2_active_ports;
|
||||
|
||||
@@ -34,32 +36,33 @@ void bio2emu_init()
|
||||
bio2emu_setupapi_hook_init(&bio2_active_ports);
|
||||
}
|
||||
|
||||
void bio2emu_port_init(struct bio2emu_port* bio2_emu)
|
||||
void bio2emu_port_init(struct bio2emu_port *bio2_emu)
|
||||
{
|
||||
// BIO2 seems like ACIO with just 1 device
|
||||
ac_io_emu_init(&bio2_emu->acio, bio2_emu->wport);
|
||||
rs232_hook_add_fd(bio2_emu->acio.fd);
|
||||
|
||||
*array_append(struct bio2emu_port*, &bio2_active_ports) = bio2_emu;
|
||||
*array_append(struct bio2emu_port *, &bio2_active_ports) = bio2_emu;
|
||||
}
|
||||
|
||||
void bio2emu_port_fini(struct bio2emu_port* bio2_emu)
|
||||
void bio2emu_port_fini(struct bio2emu_port *bio2_emu)
|
||||
{
|
||||
ac_io_emu_fini(&bio2_emu->acio);
|
||||
}
|
||||
|
||||
HRESULT bio2emu_port_dispatch_irp(struct irp *irp)
|
||||
HRESULT
|
||||
bio2emu_port_dispatch_irp(struct irp *irp)
|
||||
{
|
||||
const struct ac_io_message *msg;
|
||||
HRESULT hr;
|
||||
|
||||
log_assert(irp != NULL);
|
||||
|
||||
struct bio2emu_port* check = NULL;
|
||||
struct bio2emu_port* selected_emu = NULL;
|
||||
struct bio2emu_port *check = NULL;
|
||||
struct bio2emu_port *selected_emu = NULL;
|
||||
|
||||
for (size_t i = 0 ; i < bio2_active_ports.nitems ; i++) {
|
||||
check = *array_item(struct bio2emu_port*, &bio2_active_ports, i);
|
||||
for (size_t i = 0; i < bio2_active_ports.nitems; i++) {
|
||||
check = *array_item(struct bio2emu_port *, &bio2_active_ports, i);
|
||||
if (ac_io_emu_match_irp(&check->acio, irp)) {
|
||||
selected_emu = check;
|
||||
}
|
||||
@@ -69,7 +72,7 @@ HRESULT bio2emu_port_dispatch_irp(struct irp *irp)
|
||||
return irp_invoke_next(irp);
|
||||
}
|
||||
|
||||
struct ac_io_emu* emu = &selected_emu->acio;
|
||||
struct ac_io_emu *emu = &selected_emu->acio;
|
||||
|
||||
for (;;) {
|
||||
hr = ac_io_emu_dispatch_irp(emu, irp);
|
||||
@@ -81,21 +84,22 @@ HRESULT bio2emu_port_dispatch_irp(struct irp *irp)
|
||||
msg = ac_io_emu_request_peek(emu);
|
||||
|
||||
switch (msg->addr) {
|
||||
case 0:
|
||||
ac_io_emu_cmd_assign_addrs(emu, msg, 1);
|
||||
break;
|
||||
case 0:
|
||||
ac_io_emu_cmd_assign_addrs(emu, msg, 1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
selected_emu->dispatcher(selected_emu, msg);
|
||||
break;
|
||||
case 1:
|
||||
selected_emu->dispatcher(selected_emu, msg);
|
||||
break;
|
||||
|
||||
case AC_IO_BROADCAST:
|
||||
log_warning("Broadcast(?) message on BIO2 bus?");
|
||||
break;
|
||||
case AC_IO_BROADCAST:
|
||||
log_warning("Broadcast(?) message on BIO2 bus?");
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("BIO2 message on unhandled bus address: %d", msg->addr);
|
||||
break;
|
||||
default:
|
||||
log_warning(
|
||||
"BIO2 message on unhandled bus address: %d", msg->addr);
|
||||
break;
|
||||
}
|
||||
|
||||
ac_io_emu_request_pop(emu);
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
#ifndef BIO2EMU_EMU_H
|
||||
#define BIO2EMU_EMU_H
|
||||
|
||||
#include "hook/iohook.h"
|
||||
#include "acioemu/emu.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
struct bio2emu_port;
|
||||
struct ac_io_message;
|
||||
|
||||
typedef void (*bio2_bi2a_dispatcher)(struct bio2emu_port *emu, const struct ac_io_message *req);
|
||||
typedef void (*bio2_bi2a_dispatcher)(
|
||||
struct bio2emu_port *emu, const struct ac_io_message *req);
|
||||
|
||||
struct bio2emu_port {
|
||||
struct ac_io_emu acio;
|
||||
const char* port;
|
||||
const wchar_t* wport;
|
||||
const char *port;
|
||||
const wchar_t *wport;
|
||||
bio2_bi2a_dispatcher dispatcher;
|
||||
};
|
||||
|
||||
|
||||
void bio2emu_init();
|
||||
|
||||
void bio2emu_port_init(struct bio2emu_port* bio2emu_emu);
|
||||
void bio2emu_port_fini(struct bio2emu_port* bio2emu_emu);
|
||||
void bio2emu_port_init(struct bio2emu_port *bio2emu_emu);
|
||||
void bio2emu_port_fini(struct bio2emu_port *bio2emu_emu);
|
||||
|
||||
HRESULT bio2emu_port_dispatch_irp(struct irp *irp);
|
||||
|
||||
|
||||
@@ -1,32 +1,43 @@
|
||||
#define LOG_MODULE "setupapi-hook"
|
||||
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <setupapi.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <setupapi.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "bio2emu/setupapi.h"
|
||||
#include "bio2emu/emu.h"
|
||||
#include "bio2emu/setupapi.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static struct array* bio2_assigned_ports = NULL;
|
||||
static struct array *bio2_assigned_ports = NULL;
|
||||
|
||||
DEFINE_GUID(GUID_COM_BUS_ENUMERATOR,
|
||||
0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
|
||||
DEFINE_GUID(
|
||||
GUID_COM_BUS_ENUMERATOR,
|
||||
0x4D36E978,
|
||||
0xE325,
|
||||
0x11CE,
|
||||
0xBF,
|
||||
0xC1,
|
||||
0x08,
|
||||
0x00,
|
||||
0x2B,
|
||||
0xE1,
|
||||
0x03,
|
||||
0x18);
|
||||
|
||||
#define MAX_INSTANCES_HOOKED 16
|
||||
#define CUSTOM_DEVICE_INSTANCE 0x3113ca70
|
||||
#define CUSTOM_DEVICE_INSTANCE_MASK 0xfffffff0
|
||||
#define CUSTOM_DEVICE_INSTANCE_IDXMASK 0x0000000f
|
||||
|
||||
static void* CUSTOM_DEVICE_HANDLE;
|
||||
static void *CUSTOM_DEVICE_HANDLE;
|
||||
|
||||
static struct HKEY__ CUSTOM_REGISTRY_HANDLE[MAX_INSTANCES_HOOKED];
|
||||
|
||||
@@ -37,14 +48,15 @@ static const size_t DEVICE_PROPERTY_LENGTH = 12;
|
||||
static const char devpath[] = "USB\\VID_5730&PID_804C&MI_00\\000";
|
||||
static const size_t devpathsize = 32;
|
||||
|
||||
|
||||
// check if HKEY handle is one of ours
|
||||
static BOOL check_if_match(HKEY ptr, HKEY base) {
|
||||
static BOOL check_if_match(HKEY ptr, HKEY base)
|
||||
{
|
||||
return (ptr >= &base[0]) && (ptr <= &base[MAX_INSTANCES_HOOKED - 1]);
|
||||
}
|
||||
|
||||
// turn HKEY handle back into idx
|
||||
static size_t get_match_index(HKEY ptr, HKEY base) {
|
||||
static size_t get_match_index(HKEY ptr, HKEY base)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_INSTANCES_HOOKED; ++i) {
|
||||
if (ptr == &base[i]) {
|
||||
return i;
|
||||
@@ -54,7 +66,8 @@ static size_t get_match_index(HKEY ptr, HKEY base) {
|
||||
}
|
||||
|
||||
// check if devinst is on of ours (can't use pointer since this is a DWORD)
|
||||
static BOOL check_instances_limit(DWORD devinst) {
|
||||
static BOOL check_instances_limit(DWORD devinst)
|
||||
{
|
||||
if ((devinst & CUSTOM_DEVICE_INSTANCE_MASK) != CUSTOM_DEVICE_INSTANCE) {
|
||||
return false;
|
||||
}
|
||||
@@ -75,169 +88,118 @@ static BOOL check_instances_limit(DWORD devinst) {
|
||||
// hooked functions
|
||||
//
|
||||
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(
|
||||
HDEVINFO DeviceInfoSet
|
||||
);
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
|
||||
|
||||
static BOOL (*real_SetupDiDestroyDeviceInfoList)(
|
||||
HDEVINFO DeviceInfoSet
|
||||
);
|
||||
static BOOL (*real_SetupDiDestroyDeviceInfoList)(HDEVINFO DeviceInfoSet);
|
||||
|
||||
static BOOL my_SetupDiEnumDeviceInfo(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
DWORD MemberIndex,
|
||||
PSP_DEVINFO_DATA DeviceInfoData
|
||||
);
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
static BOOL (*real_SetupDiEnumDeviceInfo)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
DWORD MemberIndex,
|
||||
PSP_DEVINFO_DATA DeviceInfoData
|
||||
);
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
static HKEY my_SetupDiOpenDevRegKey(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired
|
||||
);
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired);
|
||||
|
||||
static HKEY (*real_SetupDiOpenDevRegKey)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired
|
||||
);
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired);
|
||||
|
||||
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize
|
||||
);
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize);
|
||||
|
||||
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize
|
||||
);
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize);
|
||||
|
||||
static BOOL my_SetupDiGetDeviceInfoListDetailA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
|
||||
);
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData);
|
||||
|
||||
static BOOL (*real_SetupDiGetDeviceInfoListDetailA)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
|
||||
);
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData);
|
||||
|
||||
static HDEVINFO my_SetupDiGetClassDevsA(
|
||||
CONST GUID *ClassGuid,
|
||||
PCSTR Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags
|
||||
);
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags);
|
||||
|
||||
static HDEVINFO(*real_SetupDiGetClassDevsA)(
|
||||
CONST GUID *ClassGuid,
|
||||
PCSTR Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags
|
||||
);
|
||||
static HDEVINFO (*real_SetupDiGetClassDevsA)(
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags);
|
||||
|
||||
static CONFIGRET my_CM_Get_Device_IDA(
|
||||
DEVINST dnDevInst,
|
||||
PSTR Buffer,
|
||||
ULONG BufferLen,
|
||||
ULONG ulFlags
|
||||
);
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET(*real_CM_Get_Device_IDA)(
|
||||
DEVINST dnDevInst,
|
||||
PSTR Buffer,
|
||||
ULONG BufferLen,
|
||||
ULONG ulFlags
|
||||
);
|
||||
static CONFIGRET (*real_CM_Get_Device_IDA)(
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
|
||||
static const struct hook_symbol bio2emu_setupapi_syms[] = {
|
||||
{
|
||||
.name = "SetupDiDestroyDeviceInfoList",
|
||||
.patch = my_SetupDiDestroyDeviceInfoList,
|
||||
.link = (void **) &real_SetupDiDestroyDeviceInfoList
|
||||
},
|
||||
{
|
||||
.name = "SetupDiEnumDeviceInfo",
|
||||
.patch = my_SetupDiEnumDeviceInfo,
|
||||
.link = (void **) &real_SetupDiEnumDeviceInfo
|
||||
},
|
||||
{
|
||||
.name = "SetupDiOpenDevRegKey",
|
||||
.patch = my_SetupDiOpenDevRegKey,
|
||||
.link = (void **) &real_SetupDiOpenDevRegKey
|
||||
},
|
||||
{
|
||||
.name = "SetupDiGetDeviceRegistryPropertyA",
|
||||
.patch = my_SetupDiGetDeviceRegistryPropertyA,
|
||||
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA
|
||||
},
|
||||
{
|
||||
.name = "SetupDiGetDeviceInfoListDetailA",
|
||||
.patch = my_SetupDiGetDeviceInfoListDetailA,
|
||||
.link = (void **) &real_SetupDiGetDeviceInfoListDetailA
|
||||
},
|
||||
{
|
||||
.name = "SetupDiGetClassDevsA",
|
||||
.patch = my_SetupDiGetClassDevsA,
|
||||
.link = (void **) &real_SetupDiGetClassDevsA
|
||||
},
|
||||
{
|
||||
.name = "CM_Get_Device_IDA",
|
||||
.patch = my_CM_Get_Device_IDA,
|
||||
.link = (void **) &real_CM_Get_Device_IDA
|
||||
},
|
||||
{.name = "SetupDiDestroyDeviceInfoList",
|
||||
.patch = my_SetupDiDestroyDeviceInfoList,
|
||||
.link = (void **) &real_SetupDiDestroyDeviceInfoList},
|
||||
{.name = "SetupDiEnumDeviceInfo",
|
||||
.patch = my_SetupDiEnumDeviceInfo,
|
||||
.link = (void **) &real_SetupDiEnumDeviceInfo},
|
||||
{.name = "SetupDiOpenDevRegKey",
|
||||
.patch = my_SetupDiOpenDevRegKey,
|
||||
.link = (void **) &real_SetupDiOpenDevRegKey},
|
||||
{.name = "SetupDiGetDeviceRegistryPropertyA",
|
||||
.patch = my_SetupDiGetDeviceRegistryPropertyA,
|
||||
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA},
|
||||
{.name = "SetupDiGetDeviceInfoListDetailA",
|
||||
.patch = my_SetupDiGetDeviceInfoListDetailA,
|
||||
.link = (void **) &real_SetupDiGetDeviceInfoListDetailA},
|
||||
{.name = "SetupDiGetClassDevsA",
|
||||
.patch = my_SetupDiGetClassDevsA,
|
||||
.link = (void **) &real_SetupDiGetClassDevsA},
|
||||
{.name = "CM_Get_Device_IDA",
|
||||
.patch = my_CM_Get_Device_IDA,
|
||||
.link = (void **) &real_CM_Get_Device_IDA},
|
||||
};
|
||||
|
||||
static LSTATUS my_RegQueryValueExA(
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData
|
||||
);
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData);
|
||||
static LSTATUS (*real_RegQueryValueExA)(
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData
|
||||
);
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData);
|
||||
|
||||
static const struct hook_symbol bio2emu_Advapi32_syms[] = {
|
||||
{
|
||||
.name = "RegQueryValueExA",
|
||||
.patch = my_RegQueryValueExA,
|
||||
.link = (void **) &real_RegQueryValueExA
|
||||
},
|
||||
{.name = "RegQueryValueExA",
|
||||
.patch = my_RegQueryValueExA,
|
||||
.link = (void **) &real_RegQueryValueExA},
|
||||
};
|
||||
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(
|
||||
HDEVINFO DeviceInfoSet
|
||||
){
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet)
|
||||
{
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE) {
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
return true;
|
||||
}
|
||||
@@ -246,11 +208,9 @@ static BOOL my_SetupDiDestroyDeviceInfoList(
|
||||
}
|
||||
|
||||
static BOOL my_SetupDiEnumDeviceInfo(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
DWORD MemberIndex,
|
||||
PSP_DEVINFO_DATA DeviceInfoData
|
||||
){
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE) {
|
||||
log_info("%s: Loaded idx %ld", __FUNCTION__, MemberIndex);
|
||||
if (MemberIndex < bio2_assigned_ports->nitems) {
|
||||
DeviceInfoData->DevInst = CUSTOM_DEVICE_INSTANCE | MemberIndex;
|
||||
@@ -258,49 +218,62 @@ static BOOL my_SetupDiEnumDeviceInfo(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return real_SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, DeviceInfoData);
|
||||
return real_SetupDiEnumDeviceInfo(
|
||||
DeviceInfoSet, MemberIndex, DeviceInfoData);
|
||||
}
|
||||
|
||||
static HKEY my_SetupDiOpenDevRegKey(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired
|
||||
){
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
|
||||
if (check_instances_limit(DeviceInfoData->DevInst)){
|
||||
DWORD Scope,
|
||||
DWORD HwProfile,
|
||||
DWORD KeyType,
|
||||
REGSAM samDesired)
|
||||
{
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE) {
|
||||
if (check_instances_limit(DeviceInfoData->DevInst)) {
|
||||
log_info("%s: matched instance", __FUNCTION__);
|
||||
return &CUSTOM_REGISTRY_HANDLE[DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK];
|
||||
return &CUSTOM_REGISTRY_HANDLE
|
||||
[DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK];
|
||||
}
|
||||
}
|
||||
return real_SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired);
|
||||
return real_SetupDiOpenDevRegKey(
|
||||
DeviceInfoSet, DeviceInfoData, Scope, HwProfile, KeyType, samDesired);
|
||||
}
|
||||
|
||||
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize
|
||||
){
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
|
||||
if (check_instances_limit(DeviceInfoData->DevInst)){
|
||||
struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK);
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize)
|
||||
{
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE) {
|
||||
if (check_instances_limit(DeviceInfoData->DevInst)) {
|
||||
struct bio2emu_port *selected_port = *array_item(
|
||||
struct bio2emu_port *,
|
||||
bio2_assigned_ports,
|
||||
DeviceInfoData->DevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK);
|
||||
size_t portname_len = strlen(selected_port->port);
|
||||
size_t required_size = (DEVICE_PROPERTY_LENGTH + portname_len + 1 + 1); // + 1 for ')', + 1 for NULL
|
||||
size_t required_size =
|
||||
(DEVICE_PROPERTY_LENGTH + portname_len + 1 +
|
||||
1); // + 1 for ')', + 1 for NULL
|
||||
|
||||
if (PropertyBuffer && (PropertyBufferSize >= required_size)){
|
||||
char* PropBuffStr = (char*)PropertyBuffer;
|
||||
if (PropertyBuffer && (PropertyBufferSize >= required_size)) {
|
||||
char *PropBuffStr = (char *) PropertyBuffer;
|
||||
|
||||
strcpy(PropBuffStr, DEVICE_PROPERTY_VALUE);
|
||||
strcpy(PropBuffStr + DEVICE_PROPERTY_LENGTH, selected_port->port);
|
||||
strcpy(PropBuffStr + DEVICE_PROPERTY_LENGTH + portname_len, ")");
|
||||
strcpy(
|
||||
PropBuffStr + DEVICE_PROPERTY_LENGTH, selected_port->port);
|
||||
strcpy(
|
||||
PropBuffStr + DEVICE_PROPERTY_LENGTH + portname_len, ")");
|
||||
|
||||
log_info("%s: Done copying property name [%s]", __FUNCTION__, PropBuffStr);
|
||||
log_info(
|
||||
"%s: Done copying property name [%s]",
|
||||
__FUNCTION__,
|
||||
PropBuffStr);
|
||||
} else {
|
||||
log_info("%s: Returning size", __FUNCTION__);
|
||||
*RequiredSize = required_size;
|
||||
@@ -309,28 +282,33 @@ static BOOL my_SetupDiGetDeviceRegistryPropertyA(
|
||||
log_info("%s: STUB RETURN", __FUNCTION__);
|
||||
return true;
|
||||
}
|
||||
return real_SetupDiGetDeviceRegistryPropertyA(DeviceInfoSet, DeviceInfoData, Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, RequiredSize);
|
||||
return real_SetupDiGetDeviceRegistryPropertyA(
|
||||
DeviceInfoSet,
|
||||
DeviceInfoData,
|
||||
Property,
|
||||
PropertyRegDataType,
|
||||
PropertyBuffer,
|
||||
PropertyBufferSize,
|
||||
RequiredSize);
|
||||
}
|
||||
|
||||
static BOOL my_SetupDiGetDeviceInfoListDetailA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData
|
||||
){
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE){
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_LIST_DETAIL_DATA_A DeviceInfoSetDetailData)
|
||||
{
|
||||
if (DeviceInfoSet == &CUSTOM_DEVICE_HANDLE) {
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
return true;
|
||||
}
|
||||
return real_SetupDiGetDeviceInfoListDetailA(DeviceInfoSet, DeviceInfoSetDetailData);
|
||||
return real_SetupDiGetDeviceInfoListDetailA(
|
||||
DeviceInfoSet, DeviceInfoSetDetailData);
|
||||
}
|
||||
|
||||
static HDEVINFO my_SetupDiGetClassDevsA(
|
||||
CONST GUID *ClassGuid,
|
||||
PCSTR Enumerator,
|
||||
HWND hwndParent,
|
||||
DWORD Flags
|
||||
){
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags)
|
||||
{
|
||||
if (ClassGuid) {
|
||||
if (IsEqualGUID(ClassGuid, &GUID_COM_BUS_ENUMERATOR)){
|
||||
if (IsEqualGUID(ClassGuid, &GUID_COM_BUS_ENUMERATOR)) {
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
return &CUSTOM_DEVICE_HANDLE;
|
||||
}
|
||||
@@ -339,19 +317,20 @@ static HDEVINFO my_SetupDiGetClassDevsA(
|
||||
}
|
||||
|
||||
static LSTATUS my_RegQueryValueExA(
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData
|
||||
){
|
||||
if (check_if_match(hKey, CUSTOM_REGISTRY_HANDLE)){
|
||||
HKEY hKey,
|
||||
LPCSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData)
|
||||
{
|
||||
if (check_if_match(hKey, CUSTOM_REGISTRY_HANDLE)) {
|
||||
if (strcmp(lpValueName, "PortName") == 0) {
|
||||
if (lpData){
|
||||
if (lpData) {
|
||||
size_t portidx = get_match_index(hKey, CUSTOM_REGISTRY_HANDLE);
|
||||
struct bio2emu_port* selected_port = *array_item(struct bio2emu_port*, bio2_assigned_ports, portidx);
|
||||
strncpy((char*)lpData, selected_port->port, *lpcbData);
|
||||
struct bio2emu_port *selected_port = *array_item(
|
||||
struct bio2emu_port *, bio2_assigned_ports, portidx);
|
||||
strncpy((char *) lpData, selected_port->port, *lpcbData);
|
||||
|
||||
log_info("%s: Queried %s", __FUNCTION__, selected_port->port);
|
||||
return ERROR_SUCCESS;
|
||||
@@ -359,21 +338,20 @@ static LSTATUS my_RegQueryValueExA(
|
||||
return ERROR_MORE_DATA;
|
||||
}
|
||||
}
|
||||
return real_RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
return real_RegQueryValueExA(
|
||||
hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||
}
|
||||
|
||||
static CONFIGRET my_CM_Get_Device_IDA(
|
||||
DEVINST dnDevInst,
|
||||
PSTR Buffer,
|
||||
ULONG BufferLen,
|
||||
ULONG ulFlags
|
||||
){
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags)
|
||||
{
|
||||
if (Buffer && BufferLen > devpathsize) {
|
||||
if (check_instances_limit(dnDevInst)) {
|
||||
log_info("%s: Injecting custom parent ID for BIO2", __FUNCTION__);
|
||||
strcpy(Buffer, devpath);
|
||||
|
||||
Buffer[devpathsize - 1] = '\0' + (dnDevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK);
|
||||
Buffer[devpathsize - 1] =
|
||||
'\0' + (dnDevInst & CUSTOM_DEVICE_INSTANCE_IDXMASK);
|
||||
log_info("%s: %s", __FUNCTION__, Buffer);
|
||||
return CR_SUCCESS;
|
||||
}
|
||||
@@ -381,21 +359,21 @@ static CONFIGRET my_CM_Get_Device_IDA(
|
||||
return real_CM_Get_Device_IDA(dnDevInst, Buffer, BufferLen, ulFlags);
|
||||
}
|
||||
|
||||
void bio2emu_setupapi_hook_init(struct array* bio2_ports)
|
||||
void bio2emu_setupapi_hook_init(struct array *bio2_ports)
|
||||
{
|
||||
bio2_assigned_ports = bio2_ports;
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"setupapi.dll",
|
||||
bio2emu_setupapi_syms,
|
||||
lengthof(bio2emu_setupapi_syms));
|
||||
NULL,
|
||||
"setupapi.dll",
|
||||
bio2emu_setupapi_syms,
|
||||
lengthof(bio2emu_setupapi_syms));
|
||||
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"Advapi32.dll",
|
||||
bio2emu_Advapi32_syms,
|
||||
lengthof(bio2emu_Advapi32_syms));
|
||||
NULL,
|
||||
"Advapi32.dll",
|
||||
bio2emu_Advapi32_syms,
|
||||
lengthof(bio2emu_Advapi32_syms));
|
||||
|
||||
log_info("Inserted setupapi hooks");
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
#include "util/array.h"
|
||||
|
||||
void bio2emu_setupapi_hook_init(struct array* bio2_ports);
|
||||
void bio2emu_setupapi_hook_init(struct array *bio2_ports);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <windows.h>
|
||||
|
||||
// clang-format off
|
||||
// Don't format because the order is important here
|
||||
#include <ntdef.h>
|
||||
#include <devioctl.h>
|
||||
#include <ntddser.h>
|
||||
// clang-format on
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -40,7 +43,8 @@ void ac_io_bus_fini(void)
|
||||
ac_io_emu_fini(&ac_io_emu);
|
||||
}
|
||||
|
||||
HRESULT ac_io_bus_dispatch_irp(struct irp *irp)
|
||||
HRESULT
|
||||
ac_io_bus_dispatch_irp(struct irp *irp)
|
||||
{
|
||||
const struct ac_io_message *msg;
|
||||
HRESULT hr;
|
||||
@@ -82,8 +86,8 @@ HRESULT ac_io_bus_dispatch_irp(struct irp *irp)
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("ACIO message on unhandled bus address: %d",
|
||||
msg->addr);
|
||||
log_warning(
|
||||
"ACIO message on unhandled bus address: %d", msg->addr);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *config)
|
||||
log_info("Starting up BeatStream IO backend");
|
||||
|
||||
bst_io_set_loggers(
|
||||
log_body_misc,
|
||||
log_body_info,
|
||||
log_body_warning,
|
||||
log_body_fatal);
|
||||
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
|
||||
|
||||
ok = bst_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
|
||||
|
||||
@@ -50,10 +47,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *config)
|
||||
}
|
||||
|
||||
eam_io_set_loggers(
|
||||
log_body_misc,
|
||||
log_body_info,
|
||||
log_body_warning,
|
||||
log_body_fatal);
|
||||
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
|
||||
|
||||
ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
|
||||
|
||||
@@ -102,14 +96,11 @@ BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
|
||||
}
|
||||
|
||||
log_to_external(
|
||||
log_body_misc,
|
||||
log_body_info,
|
||||
log_body_warning,
|
||||
log_body_fatal);
|
||||
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
|
||||
|
||||
args_recover(&argc, &argv);
|
||||
|
||||
for (i = 1 ; i < argc ; i++) {
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] != '-') {
|
||||
continue;
|
||||
}
|
||||
@@ -133,4 +124,3 @@ BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -13,25 +13,33 @@
|
||||
#include "util/log.h"
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd, DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev);
|
||||
IDirect3D9 *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev);
|
||||
static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver);
|
||||
|
||||
static IDirect3D9 * (STDCALL *real_Direct3DCreate9)(UINT sdk_ver);
|
||||
static IDirect3D9 *(STDCALL *real_Direct3DCreate9)(UINT sdk_ver);
|
||||
|
||||
static const struct hook_symbol gfx_hook_syms[] = {
|
||||
{
|
||||
.name = "Direct3DCreate9",
|
||||
.patch = my_Direct3DCreate9,
|
||||
.link = (void **) &real_Direct3DCreate9
|
||||
},
|
||||
{.name = "Direct3DCreate9",
|
||||
.patch = my_Direct3DCreate9,
|
||||
.link = (void **) &real_Direct3DCreate9},
|
||||
};
|
||||
|
||||
static bool gfx_windowed;
|
||||
|
||||
static HRESULT STDCALL my_CreateDevice(
|
||||
IDirect3D9 *self, UINT adapter, D3DDEVTYPE type, HWND hwnd, DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp, IDirect3DDevice9 **pdev)
|
||||
IDirect3D9 *self,
|
||||
UINT adapter,
|
||||
D3DDEVTYPE type,
|
||||
HWND hwnd,
|
||||
DWORD flags,
|
||||
D3DPRESENT_PARAMETERS *pp,
|
||||
IDirect3DDevice9 **pdev)
|
||||
{
|
||||
IDirect3D9 *real = COM_PROXY_UNWRAP(self);
|
||||
HRESULT hr;
|
||||
@@ -67,11 +75,7 @@ static IDirect3D9 *STDCALL my_Direct3DCreate9(UINT sdk_ver)
|
||||
|
||||
void gfx_init(void)
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"d3d9.dll",
|
||||
gfx_hook_syms,
|
||||
lengthof(gfx_hook_syms));
|
||||
hook_table_apply(NULL, "d3d9.dll", gfx_hook_syms, lengthof(gfx_hook_syms));
|
||||
|
||||
log_info("Inserted graphics hooks");
|
||||
}
|
||||
@@ -80,4 +84,3 @@ void gfx_set_windowed(void)
|
||||
{
|
||||
gfx_windowed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,40 +30,42 @@ void kfca_dispatch_request(const struct ac_io_message *req)
|
||||
cmd_code = ac_io_u16(req->cmd.code);
|
||||
|
||||
switch (cmd_code) {
|
||||
case AC_IO_CMD_GET_VERSION:
|
||||
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
|
||||
kfca_send_version(req);
|
||||
case AC_IO_CMD_GET_VERSION:
|
||||
log_misc("AC_IO_CMD_GET_VERSION(%d)", req->addr);
|
||||
kfca_send_version(req);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_START_UP:
|
||||
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
|
||||
kfca_report_status(req, 0x00);
|
||||
case AC_IO_CMD_START_UP:
|
||||
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
|
||||
kfca_report_status(req, 0x00);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KFCA_POLL:
|
||||
kfca_poll(req);
|
||||
case AC_IO_CMD_KFCA_POLL:
|
||||
kfca_poll(req);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KFCA_WATCHDOG:
|
||||
log_misc("AC_IO_CMD_KFCA_WATCHDOG(%d)", req->addr);
|
||||
kfca_report_status(req, 0x00);
|
||||
case AC_IO_CMD_KFCA_WATCHDOG:
|
||||
log_misc("AC_IO_CMD_KFCA_WATCHDOG(%d)", req->addr);
|
||||
kfca_report_status(req, 0x00);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case AC_IO_CMD_KFCA_AMP_CONTROL:
|
||||
log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr);
|
||||
kfca_report_nil(req);
|
||||
case AC_IO_CMD_KFCA_AMP_CONTROL:
|
||||
log_misc("AC_IO_CMD_KFCA_AMP_CONTROL(%d)", req->addr);
|
||||
kfca_report_nil(req);
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_warning("Unknown ACIO message %04x on KFCA mode, addr=%d",
|
||||
cmd_code, req->addr);
|
||||
default:
|
||||
log_warning(
|
||||
"Unknown ACIO message %04x on KFCA mode, addr=%d",
|
||||
cmd_code,
|
||||
req->addr);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +82,10 @@ static void kfca_send_version(const struct ac_io_message *req)
|
||||
resp.cmd.version.major = 0x01;
|
||||
resp.cmd.version.minor = 0x01;
|
||||
resp.cmd.version.revision = 0x00;
|
||||
memcpy(resp.cmd.version.product_code, "KFCA",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
memcpy(
|
||||
resp.cmd.version.product_code,
|
||||
"KFCA",
|
||||
sizeof(resp.cmd.version.product_code));
|
||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||
|
||||
@@ -133,4 +137,3 @@ static void kfca_poll(const struct ac_io_message *req)
|
||||
|
||||
ac_io_emu_response_push(kfca_ac_io_emu, &resp, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,47 +16,43 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static HANDLE STDCALL my_CreateFileA(
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
|
||||
static HANDLE (STDCALL *real_CreateFileA)(
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
static HANDLE(STDCALL *real_CreateFileA)(
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static const struct hook_symbol settings_hook_syms[] = {
|
||||
{
|
||||
.name = "CreateFileA",
|
||||
.patch = my_CreateFileA,
|
||||
.link = (void **) &real_CreateFileA
|
||||
},
|
||||
{.name = "CreateFileA",
|
||||
.patch = my_CreateFileA,
|
||||
.link = (void **) &real_CreateFileA},
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static HANDLE STDCALL my_CreateFileA(
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile)
|
||||
LPCSTR lpFileName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile)
|
||||
{
|
||||
if ( lpFileName != NULL &&
|
||||
lpFileName[0] == 'e' &&
|
||||
lpFileName[1] == ':') {
|
||||
if (lpFileName != NULL && lpFileName[0] == 'e' && lpFileName[1] == ':') {
|
||||
HANDLE handle;
|
||||
char new_path[MAX_PATH];
|
||||
|
||||
@@ -64,28 +60,34 @@ static HANDLE STDCALL my_CreateFileA(
|
||||
new_path[1] = '\\';
|
||||
log_misc("Remapped settings path %s", new_path);
|
||||
|
||||
handle = real_CreateFileA(new_path, dwDesiredAccess, dwShareMode,
|
||||
lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
handle = real_CreateFileA(
|
||||
new_path,
|
||||
dwDesiredAccess,
|
||||
dwShareMode,
|
||||
lpSecurityAttributes,
|
||||
dwCreationDisposition,
|
||||
dwFlagsAndAttributes,
|
||||
hTemplateFile);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
return real_CreateFileA(lpFileName, dwDesiredAccess, dwShareMode,
|
||||
lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
return real_CreateFileA(
|
||||
lpFileName,
|
||||
dwDesiredAccess,
|
||||
dwShareMode,
|
||||
lpSecurityAttributes,
|
||||
dwCreationDisposition,
|
||||
dwFlagsAndAttributes,
|
||||
hTemplateFile);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void settings_hook_init(void)
|
||||
{
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"kernel32.dll",
|
||||
settings_hook_syms,
|
||||
lengthof(settings_hook_syms));
|
||||
NULL, "kernel32.dll", settings_hook_syms, lengthof(settings_hook_syms));
|
||||
|
||||
log_info("Inserted settings hooks");
|
||||
}
|
||||
|
||||
@@ -8,14 +8,19 @@
|
||||
|
||||
static uint8_t bst_io_gpio_sys;
|
||||
|
||||
void bst_io_set_loggers(log_formatter_t misc, log_formatter_t info,
|
||||
log_formatter_t warning, log_formatter_t fatal)
|
||||
void bst_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
input_set_loggers(misc, info, warning, fatal);
|
||||
}
|
||||
|
||||
bool bst_io_init(thread_create_t thread_create, thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
bool bst_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
input_init(thread_create, thread_join, thread_destroy);
|
||||
mapper_config_load("bst");
|
||||
@@ -39,4 +44,3 @@ uint8_t bst_io_get_input(void)
|
||||
{
|
||||
return bst_io_gpio_sys;
|
||||
}
|
||||
|
||||
|
||||
11
src/main/camhook/Module.mk
Normal file
11
src/main/camhook/Module.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
libs += camhook
|
||||
|
||||
libs_camhook := \
|
||||
hook \
|
||||
hooklib \
|
||||
cconfig \
|
||||
util \
|
||||
|
||||
src_camhook := \
|
||||
cam.c \
|
||||
config-cam.c \
|
||||
816
src/main/camhook/cam.c
Normal file
816
src/main/camhook/cam.c
Normal file
@@ -0,0 +1,816 @@
|
||||
#define LOG_MODULE "cam-hook"
|
||||
|
||||
// clang-format off
|
||||
// Don't format because the order is important here
|
||||
#include <windows.h>
|
||||
#include <initguid.h>
|
||||
// clang-format on
|
||||
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
#include <mfobjects.h>
|
||||
|
||||
#include <cfgmgr32.h>
|
||||
#include <setupapi.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hook/com-proxy.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "camhook/cam.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/time.h"
|
||||
|
||||
#define CAMERA_DATA_STRING_SIZE 0x100
|
||||
|
||||
EXTERN_GUID(
|
||||
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
0xc60ac5fe,
|
||||
0x252a,
|
||||
0x478f,
|
||||
0xa0,
|
||||
0xef,
|
||||
0xbc,
|
||||
0x8f,
|
||||
0xa5,
|
||||
0xf7,
|
||||
0xca,
|
||||
0xd3);
|
||||
EXTERN_GUID(
|
||||
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID,
|
||||
0x8ac3587a,
|
||||
0x4ae7,
|
||||
0x42d8,
|
||||
0x99,
|
||||
0xe0,
|
||||
0x0a,
|
||||
0x60,
|
||||
0x13,
|
||||
0xee,
|
||||
0xf9,
|
||||
0x0f);
|
||||
EXTERN_GUID(
|
||||
MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
|
||||
0x58f0aad8,
|
||||
0x22bf,
|
||||
0x4f8a,
|
||||
0xbb,
|
||||
0x3d,
|
||||
0xd2,
|
||||
0xc4,
|
||||
0x97,
|
||||
0x8c,
|
||||
0x6e,
|
||||
0x2f);
|
||||
// define ourselves cause mingw has these wrong
|
||||
|
||||
struct CameraData {
|
||||
bool setup;
|
||||
char name[CAMERA_DATA_STRING_SIZE];
|
||||
char deviceInstancePath[CAMERA_DATA_STRING_SIZE];
|
||||
wchar_t deviceSymbolicLink[CAMERA_DATA_STRING_SIZE];
|
||||
char extra_upper[CAMERA_DATA_STRING_SIZE];
|
||||
int address;
|
||||
char parent_name[CAMERA_DATA_STRING_SIZE];
|
||||
char parent_deviceInstancePath[CAMERA_DATA_STRING_SIZE];
|
||||
int parent_address;
|
||||
|
||||
bool fake_addressed;
|
||||
int fake_address;
|
||||
|
||||
bool fake_located;
|
||||
size_t fake_located_node;
|
||||
};
|
||||
|
||||
static struct CameraData camData[CAMHOOK_CONFIG_CAM_MAX];
|
||||
int camAddresses[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
1,
|
||||
7,
|
||||
};
|
||||
static size_t num_addressed_cams = 0;
|
||||
static size_t num_located_cams = 0;
|
||||
|
||||
static CONFIGRET my_CM_Locate_DevNodeA(
|
||||
PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET
|
||||
my_CM_Get_Parent(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET my_CM_Get_Device_IDA(
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET (*real_CM_Locate_DevNodeA)(
|
||||
PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET (*real_CM_Get_Parent)(
|
||||
PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags);
|
||||
|
||||
static CONFIGRET (*real_CM_Get_Device_IDA)(
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags);
|
||||
|
||||
static HRESULT my_MFEnumDeviceSources(
|
||||
IMFAttributes *pAttributes,
|
||||
IMFActivate ***pppSourceActivate,
|
||||
UINT32 *pcSourceActivate);
|
||||
|
||||
static HRESULT (*real_MFEnumDeviceSources)(
|
||||
IMFAttributes *pAttributes,
|
||||
IMFActivate ***pppSourceActivate,
|
||||
UINT32 *pcSourceActivate);
|
||||
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
|
||||
|
||||
static BOOL (*real_SetupDiDestroyDeviceInfoList)(HDEVINFO DeviceInfoSet);
|
||||
|
||||
static BOOL my_SetupDiEnumDeviceInfo(
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
static BOOL (*real_SetupDiEnumDeviceInfo)(
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize);
|
||||
|
||||
static BOOL (*real_SetupDiGetDeviceRegistryPropertyA)(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize);
|
||||
|
||||
static HDEVINFO my_SetupDiGetClassDevsA(
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags);
|
||||
|
||||
static HDEVINFO (*real_SetupDiGetClassDevsA)(
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags);
|
||||
|
||||
static const struct hook_symbol camhook_cfgmgr32_syms[] = {
|
||||
{.name = "CM_Locate_DevNodeA",
|
||||
.patch = my_CM_Locate_DevNodeA,
|
||||
.link = (void **) &real_CM_Locate_DevNodeA},
|
||||
{.name = "CM_Get_Parent",
|
||||
.patch = my_CM_Get_Parent,
|
||||
.link = (void **) &real_CM_Get_Parent},
|
||||
{.name = "CM_Get_Device_IDA",
|
||||
.patch = my_CM_Get_Device_IDA,
|
||||
.link = (void **) &real_CM_Get_Device_IDA},
|
||||
{.name = "SetupDiDestroyDeviceInfoList",
|
||||
.patch = my_SetupDiDestroyDeviceInfoList,
|
||||
.link = (void **) &real_SetupDiDestroyDeviceInfoList},
|
||||
{.name = "SetupDiEnumDeviceInfo",
|
||||
.patch = my_SetupDiEnumDeviceInfo,
|
||||
.link = (void **) &real_SetupDiEnumDeviceInfo},
|
||||
{.name = "SetupDiGetDeviceRegistryPropertyA",
|
||||
.patch = my_SetupDiGetDeviceRegistryPropertyA,
|
||||
.link = (void **) &real_SetupDiGetDeviceRegistryPropertyA},
|
||||
{.name = "SetupDiGetClassDevsA",
|
||||
.patch = my_SetupDiGetClassDevsA,
|
||||
.link = (void **) &real_SetupDiGetClassDevsA},
|
||||
};
|
||||
|
||||
static const struct hook_symbol camhook_mf_syms[] = {
|
||||
{.name = "MFEnumDeviceSources",
|
||||
.patch = my_MFEnumDeviceSources,
|
||||
.link = (void **) &real_MFEnumDeviceSources},
|
||||
};
|
||||
|
||||
DEVINST camhook_custom_nodes[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
0x04040004,
|
||||
0x04040008,
|
||||
};
|
||||
DEVINST camhook_custom_parent_nodes[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
0x04040014,
|
||||
0x04040018,
|
||||
};
|
||||
const char *camhook_custom_parent_device_id[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
"USB\\VEN_1022&DEV_7908",
|
||||
"USB\\VEN_1022&DEV_7914",
|
||||
};
|
||||
|
||||
static CONFIGRET
|
||||
my_CM_Locate_DevNodeA(PDEVINST pdnDevInst, DEVINSTID_A pDeviceID, ULONG ulFlags)
|
||||
{
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
|
||||
char builtString[CAMERA_DATA_STRING_SIZE] = {0};
|
||||
if (pdnDevInst) {
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (camData[i].setup) {
|
||||
snprintf(
|
||||
builtString,
|
||||
CAMERA_DATA_STRING_SIZE,
|
||||
"USB\\VID_288C&PID_0002&MI_00\\%s",
|
||||
camData[i].extra_upper);
|
||||
if (strcmp(pDeviceID, builtString) == 0) {
|
||||
if (!camData[i].fake_located) {
|
||||
camData[i].fake_located_node = num_located_cams;
|
||||
camData[i].fake_located = true;
|
||||
++num_located_cams;
|
||||
}
|
||||
log_info(
|
||||
"Injecting custom device %d to node %x",
|
||||
(int) i,
|
||||
(int) camData[i].fake_located_node);
|
||||
*pdnDevInst =
|
||||
camhook_custom_nodes[camData[i].fake_located_node];
|
||||
return CR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return real_CM_Locate_DevNodeA(pdnDevInst, pDeviceID, ulFlags);
|
||||
}
|
||||
|
||||
static CONFIGRET
|
||||
my_CM_Get_Parent(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags)
|
||||
{
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
|
||||
if (pdnDevInst) {
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (dnDevInst == camhook_custom_nodes[i]) {
|
||||
log_info("Injecting custom parent %d", (int) i);
|
||||
*pdnDevInst = camhook_custom_parent_nodes[i];
|
||||
return CR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return real_CM_Get_Parent(pdnDevInst, dnDevInst, ulFlags);
|
||||
}
|
||||
|
||||
static CONFIGRET my_CM_Get_Device_IDA(
|
||||
DEVINST dnDevInst, PSTR Buffer, ULONG BufferLen, ULONG ulFlags)
|
||||
{
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
if (Buffer) {
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (dnDevInst == camhook_custom_parent_nodes[i]) {
|
||||
log_info("Injecting custom parent %d ID", (int) i);
|
||||
strncpy(Buffer, camhook_custom_parent_device_id[i], BufferLen);
|
||||
Buffer[BufferLen - 1] = '\0';
|
||||
log_info("%s", Buffer);
|
||||
return CR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return real_CM_Get_Device_IDA(dnDevInst, Buffer, BufferLen, ulFlags);
|
||||
}
|
||||
|
||||
static HRESULT(STDCALL *real_GetAllocatedString)(
|
||||
IMFActivate *self, REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength);
|
||||
|
||||
HRESULT my_GetAllocatedString(
|
||||
IMFActivate *self, REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength)
|
||||
{
|
||||
HRESULT ret;
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
|
||||
// should probably check GUID, oh well
|
||||
ret = real_GetAllocatedString(self, guidKey, ppwszValue, pcchLength);
|
||||
log_info("Obtained: %ls", *ppwszValue);
|
||||
|
||||
wchar_t *pwc = NULL;
|
||||
|
||||
// look for a matching deviceSymbolicLink
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (!pwc) {
|
||||
if (camData[i].setup) {
|
||||
pwc = wcsstr(*ppwszValue, camData[i].deviceSymbolicLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if matches, replace with target device ID
|
||||
if (pwc) {
|
||||
// \\?\usb#vid_288c&pid_0002&mi_00
|
||||
pwc[12] = L'2';
|
||||
pwc[13] = L'8';
|
||||
pwc[14] = L'8';
|
||||
pwc[15] = L'c';
|
||||
|
||||
pwc[21] = L'0';
|
||||
pwc[22] = L'0';
|
||||
pwc[23] = L'0';
|
||||
pwc[24] = L'2';
|
||||
|
||||
pwc[29] = L'0';
|
||||
pwc[30] = L'0';
|
||||
log_info("Replaced: %ls", *ppwszValue);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT my_MFEnumDeviceSources(
|
||||
IMFAttributes *pAttributes,
|
||||
IMFActivate ***pppSourceActivate,
|
||||
UINT32 *pcSourceActivate)
|
||||
{
|
||||
IMFActivate *api;
|
||||
IMFActivateVtbl *api_vtbl;
|
||||
struct com_proxy *api_proxy;
|
||||
|
||||
UINT32 nsrcs;
|
||||
|
||||
HRESULT ret;
|
||||
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
ret = real_MFEnumDeviceSources(
|
||||
pAttributes, pppSourceActivate, pcSourceActivate);
|
||||
nsrcs = *pcSourceActivate;
|
||||
|
||||
for (UINT32 i = 0; i < nsrcs; ++i) {
|
||||
api = (*pppSourceActivate)[i];
|
||||
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
|
||||
api_vtbl = api_proxy->vptr;
|
||||
|
||||
real_GetAllocatedString = api_vtbl->GetAllocatedString;
|
||||
api_vtbl->GetAllocatedString = my_GetAllocatedString;
|
||||
|
||||
(*pppSourceActivate)[i] = (IMFActivate *) api_proxy;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CUSTOM_DEVICE_HANDLE (void *) 0x04041110
|
||||
static HDEVINFO RealReplacedHandle;
|
||||
|
||||
static BOOL my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet)
|
||||
{
|
||||
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE) {
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
DeviceInfoSet = RealReplacedHandle;
|
||||
RealReplacedHandle = NULL;
|
||||
|
||||
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
}
|
||||
|
||||
return real_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
}
|
||||
|
||||
static BOOL my_SetupDiEnumDeviceInfo(
|
||||
HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE) {
|
||||
// log_info("Inside: %s", __FUNCTION__);
|
||||
return real_SetupDiEnumDeviceInfo(
|
||||
RealReplacedHandle, MemberIndex, DeviceInfoData);
|
||||
}
|
||||
|
||||
return real_SetupDiEnumDeviceInfo(
|
||||
DeviceInfoSet, MemberIndex, DeviceInfoData);
|
||||
}
|
||||
|
||||
static BOOL my_SetupDiGetDeviceRegistryPropertyA(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property,
|
||||
PDWORD PropertyRegDataType,
|
||||
PBYTE PropertyBuffer,
|
||||
DWORD PropertyBufferSize,
|
||||
PDWORD RequiredSize)
|
||||
{
|
||||
if (DeviceInfoSet == CUSTOM_DEVICE_HANDLE) {
|
||||
BOOL ret = real_SetupDiGetDeviceRegistryPropertyA(
|
||||
RealReplacedHandle,
|
||||
DeviceInfoData,
|
||||
Property,
|
||||
PropertyRegDataType,
|
||||
PropertyBuffer,
|
||||
PropertyBufferSize,
|
||||
RequiredSize);
|
||||
|
||||
if (Property == SPDRP_DEVICEDESC) {
|
||||
if (PropertyBuffer) {
|
||||
char *PropertyBufferChar = (char *) PropertyBuffer;
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (camData[i].setup) {
|
||||
if (strcmp(
|
||||
PropertyBufferChar, camData[i].parent_name) ==
|
||||
0) {
|
||||
log_info(
|
||||
"%s: replacing %s",
|
||||
__FUNCTION__,
|
||||
camData[i].parent_name);
|
||||
strncpy(
|
||||
PropertyBufferChar,
|
||||
"USB Composite Device",
|
||||
PropertyBufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if (Property == SPDRP_ADDRESS) {
|
||||
if (PropertyBuffer) {
|
||||
int addr = *(int *) PropertyBuffer;
|
||||
for (size_t i = 0; i < CAMHOOK_CONFIG_CAM_MAX; ++i) {
|
||||
if (camData[i].setup) {
|
||||
if (addr == camData[i].parent_address) {
|
||||
if (!camData[i].fake_addressed) {
|
||||
camData[i].fake_address =
|
||||
camAddresses[num_addressed_cams];
|
||||
camData[i].fake_addressed = true;
|
||||
++num_addressed_cams;
|
||||
}
|
||||
log_info(
|
||||
"%s: assigning cam %d to addr %d",
|
||||
__FUNCTION__,
|
||||
(int) i,
|
||||
camData[i].fake_address);
|
||||
*(int *) PropertyBuffer = camData[i].fake_address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return real_SetupDiGetDeviceRegistryPropertyA(
|
||||
DeviceInfoSet,
|
||||
DeviceInfoData,
|
||||
Property,
|
||||
PropertyRegDataType,
|
||||
PropertyBuffer,
|
||||
PropertyBufferSize,
|
||||
RequiredSize);
|
||||
}
|
||||
|
||||
static HDEVINFO my_SetupDiGetClassDevsA(
|
||||
CONST GUID *ClassGuid, PCSTR Enumerator, HWND hwndParent, DWORD Flags)
|
||||
{
|
||||
if (ClassGuid == NULL && Enumerator != NULL && hwndParent == NULL &&
|
||||
Flags == (DIGCF_PRESENT | DIGCF_ALLCLASSES)) {
|
||||
if (RealReplacedHandle) {
|
||||
log_info("Replacement handle is already set?");
|
||||
}
|
||||
|
||||
if (strcmp(Enumerator, "USB") == 0) {
|
||||
log_info("Inside: %s", __FUNCTION__);
|
||||
RealReplacedHandle = real_SetupDiGetClassDevsA(
|
||||
ClassGuid, Enumerator, hwndParent, Flags);
|
||||
|
||||
if (RealReplacedHandle == INVALID_HANDLE_VALUE) {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return CUSTOM_DEVICE_HANDLE;
|
||||
}
|
||||
}
|
||||
return real_SetupDiGetClassDevsA(ClassGuid, Enumerator, hwndParent, Flags);
|
||||
}
|
||||
|
||||
bool check_four(const char inA[4], const char inB[4])
|
||||
{
|
||||
return (*(uint32_t *) inA == *(uint32_t *) inB);
|
||||
}
|
||||
|
||||
char *grab_next_camera_id(char *buffer, size_t bsz)
|
||||
{
|
||||
static size_t gotten = 0;
|
||||
|
||||
IMFAttributes *pAttributes = NULL;
|
||||
IMFActivate **ppDevices = NULL;
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
HRESULT hr = MFCreateAttributes(&pAttributes, 1);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
log_info("MFCreateAttributes failed: %ld", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
hr = pAttributes->lpVtbl->SetGUID(
|
||||
pAttributes,
|
||||
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
|
||||
if (FAILED(hr)) {
|
||||
log_info("SetGUID failed: %ld", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
UINT32 count;
|
||||
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
log_info("MFEnumDeviceSources failed: %ld", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (count <= gotten) {
|
||||
log_info("gotten failed: %d < %d", count, (int) gotten);
|
||||
// not enough remaining
|
||||
goto done;
|
||||
}
|
||||
|
||||
wchar_t wSymLink[CAMERA_DATA_STRING_SIZE];
|
||||
UINT32 sz;
|
||||
|
||||
hr = ppDevices[gotten]->lpVtbl->GetString(
|
||||
ppDevices[gotten],
|
||||
&MY_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
|
||||
wSymLink,
|
||||
CAMERA_DATA_STRING_SIZE,
|
||||
&sz);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
log_info("GetString failed: %ld", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
log_info("Detected webcam: %s\n", buffer);
|
||||
wcstombs(buffer, wSymLink, bsz);
|
||||
++gotten;
|
||||
|
||||
done:
|
||||
if (pAttributes) {
|
||||
pAttributes->lpVtbl->Release(pAttributes);
|
||||
}
|
||||
|
||||
for (DWORD i = 0; i < count; i++) {
|
||||
if (ppDevices != NULL && ppDevices[i]) {
|
||||
ppDevices[i]->lpVtbl->Release(ppDevices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(ppDevices);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool convert_sym_to_path(const char *sym, char *path)
|
||||
{
|
||||
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
|
||||
|
||||
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
|
||||
log_info("Could not open SetupDiCreateDeviceInfoList\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = {0};
|
||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
if (!SetupDiOpenDeviceInterfaceA(
|
||||
DeviceInfoSet, sym, 0, &DeviceInterfaceData)) {
|
||||
log_info("Could not SetupDiOpenDeviceInterfaceA\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SP_DEVINFO_DATA DeviceInfoData = {0};
|
||||
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
if (!SetupDiGetDeviceInterfaceDetailA(
|
||||
DeviceInfoSet,
|
||||
&DeviceInterfaceData,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&DeviceInfoData)) {
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
log_info("Could not SetupDiGetDeviceInterfaceDetailA\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD sz;
|
||||
|
||||
if (!SetupDiGetDeviceInstanceIdA(
|
||||
DeviceInfoSet,
|
||||
&DeviceInfoData,
|
||||
path,
|
||||
CAMERA_DATA_STRING_SIZE,
|
||||
&sz)) {
|
||||
log_info("Could not SetupDiGetDeviceInstanceIdA\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
|
||||
if (!SetupDiDeleteDeviceInterfaceData(
|
||||
DeviceInfoSet, &DeviceInterfaceData)) {
|
||||
log_info("Could not SetupDiDeleteDeviceInterfaceData\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void strtolower(char *str)
|
||||
{
|
||||
for (size_t i = 0; str[i]; i++) {
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool convert_path_to_fakesym(const char *path, wchar_t *sym, char *extra_o)
|
||||
{
|
||||
char root[16] = {0};
|
||||
char vidstr[16] = {0};
|
||||
char pidstr[16] = {0};
|
||||
char mistr[16] = {0};
|
||||
char extra[64] = {0};
|
||||
sscanf(
|
||||
path,
|
||||
"%[^\\]\\%[^&]&%[^&]&%[^\\]\\%s",
|
||||
root,
|
||||
vidstr,
|
||||
pidstr,
|
||||
mistr,
|
||||
extra);
|
||||
strcpy(extra_o, extra);
|
||||
|
||||
strtolower(root);
|
||||
strtolower(vidstr);
|
||||
strtolower(pidstr);
|
||||
strtolower(mistr);
|
||||
strtolower(extra);
|
||||
|
||||
swprintf(
|
||||
sym,
|
||||
CAMERA_DATA_STRING_SIZE,
|
||||
L"\\\\?\\%S#%S&%S&%S#%S",
|
||||
root,
|
||||
vidstr,
|
||||
pidstr,
|
||||
mistr,
|
||||
extra);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fill_cam_struct(struct CameraData *data, const char *devid)
|
||||
{
|
||||
char buffer[CAMERA_DATA_STRING_SIZE];
|
||||
|
||||
data->setup = false;
|
||||
|
||||
if (!devid || strlen(devid) == 0) {
|
||||
devid = grab_next_camera_id(buffer, CAMERA_DATA_STRING_SIZE);
|
||||
}
|
||||
|
||||
if (!devid || strlen(devid) == 0) {
|
||||
// no more cameras remain?
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(devid) >= CAMERA_DATA_STRING_SIZE) {
|
||||
// error probably log something?
|
||||
return;
|
||||
}
|
||||
|
||||
// detect input type
|
||||
if (check_four(devid, "\\\\?\\")) {
|
||||
// SYMBOLIC_LINK
|
||||
if (!convert_sym_to_path(devid, data->deviceInstancePath)) {
|
||||
log_info("Could not convert %s to path", devid);
|
||||
return;
|
||||
}
|
||||
} else if (check_four(devid, "USB\\")) {
|
||||
// Device instance path
|
||||
strcpy(data->deviceInstancePath, devid);
|
||||
// continue
|
||||
} else {
|
||||
// UNKNOWN ENTRY
|
||||
log_info("UNK: %s", devid);
|
||||
log_info("Please enter the device instance path");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!convert_path_to_fakesym(
|
||||
data->deviceInstancePath,
|
||||
data->deviceSymbolicLink,
|
||||
data->extra_upper)) {
|
||||
log_info("Could not convert %s to sym", data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("dev path: %s", data->deviceInstancePath);
|
||||
|
||||
// locate device nodes
|
||||
DEVINST dnDevInst;
|
||||
DEVINST parentDev;
|
||||
CONFIGRET cmret;
|
||||
|
||||
cmret = CM_Locate_DevNodeA(
|
||||
&dnDevInst, data->deviceInstancePath, CM_LOCATE_DEVNODE_NORMAL);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info("CM_Locate_DevNodeA fail: %s", data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
cmret = CM_Get_Parent(&parentDev, dnDevInst, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info("CM_Get_Parent fail: %s", data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
cmret = CM_Get_Device_IDA(
|
||||
parentDev, data->parent_deviceInstancePath, CAMERA_DATA_STRING_SIZE, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info("CM_Get_Device_IDA parent fail: %s", data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
ULONG szAddr;
|
||||
ULONG szDesc;
|
||||
|
||||
szAddr = 4;
|
||||
szDesc = CAMERA_DATA_STRING_SIZE;
|
||||
cmret = CM_Get_DevNode_Registry_PropertyA(
|
||||
dnDevInst, CM_DRP_ADDRESS, NULL, &data->address, &szAddr, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info(
|
||||
"CM_Get_DevNode_Registry_PropertyA fail: %s",
|
||||
data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
cmret = CM_Get_DevNode_Registry_PropertyA(
|
||||
dnDevInst, CM_DRP_DEVICEDESC, NULL, &data->name, &szDesc, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info(
|
||||
"CM_Get_DevNode_Registry_PropertyA fail: %s",
|
||||
data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
szAddr = 4;
|
||||
szDesc = CAMERA_DATA_STRING_SIZE;
|
||||
cmret = CM_Get_DevNode_Registry_PropertyA(
|
||||
parentDev, CM_DRP_ADDRESS, NULL, &data->parent_address, &szAddr, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info(
|
||||
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
|
||||
data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
cmret = CM_Get_DevNode_Registry_PropertyA(
|
||||
parentDev, CM_DRP_DEVICEDESC, NULL, &data->parent_name, &szDesc, 0);
|
||||
|
||||
if (cmret != CR_SUCCESS) {
|
||||
log_info(
|
||||
"CM_Get_DevNode_Registry_PropertyA parent fail: %s",
|
||||
data->deviceInstancePath);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("Found %s @ %d", data->name, data->address);
|
||||
log_info("Parent %s @ %d", data->parent_name, data->parent_address);
|
||||
data->setup = true;
|
||||
}
|
||||
|
||||
void camhook_init(struct camhook_config_cam *config_cam)
|
||||
{
|
||||
// fill before applying hooks
|
||||
for (size_t i = 0; i < config_cam->num_devices; ++i) {
|
||||
fill_cam_struct(&camData[i], config_cam->device_id[i]);
|
||||
}
|
||||
|
||||
size_t num_setup = 0;
|
||||
|
||||
for (size_t i = 0; i < config_cam->num_devices; ++i) {
|
||||
if (camData[i].setup) {
|
||||
num_setup++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_setup > 0) {
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"setupapi.dll",
|
||||
camhook_cfgmgr32_syms,
|
||||
lengthof(camhook_cfgmgr32_syms));
|
||||
hook_table_apply(
|
||||
NULL, "Mf.dll", camhook_mf_syms, lengthof(camhook_mf_syms));
|
||||
|
||||
log_info("Inserted cam hooks for %d cams", (int) num_setup);
|
||||
} else {
|
||||
log_info("No cams detected, not hooking");
|
||||
}
|
||||
}
|
||||
8
src/main/camhook/cam.h
Normal file
8
src/main/camhook/cam.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef CAMHOOK_CAM_H
|
||||
#define CAMHOOK_CAM_H
|
||||
|
||||
#include "camhook/config-cam.h"
|
||||
|
||||
void camhook_init(struct camhook_config_cam *config_cam);
|
||||
|
||||
#endif
|
||||
72
src/main/camhook/config-cam.c
Normal file
72
src/main/camhook/config-cam.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "camhook/config-cam.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY "cam.disable_emu"
|
||||
#define CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE false
|
||||
|
||||
// the following two arrays are based on CAMHOOK_CONFIG_CAM_MAX
|
||||
// please insert more elements if more cams are added
|
||||
const char *camhook_config_device_id_keys[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
"cam.device_id1",
|
||||
"cam.device_id2",
|
||||
};
|
||||
|
||||
const char *camhook_config_device_default_values[CAMHOOK_CONFIG_CAM_MAX] = {
|
||||
"",
|
||||
"",
|
||||
};
|
||||
|
||||
void camhook_config_cam_init(struct cconfig *config, size_t num_cams)
|
||||
{
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY,
|
||||
CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE,
|
||||
"Disables the camera emulation");
|
||||
|
||||
for (size_t i = 0; i < num_cams; ++i) {
|
||||
cconfig_util_set_str(
|
||||
config,
|
||||
camhook_config_device_id_keys[i],
|
||||
camhook_config_device_default_values[i],
|
||||
"Override camera device ID detection (copy from device manager, do "
|
||||
"not escape)");
|
||||
}
|
||||
}
|
||||
|
||||
void camhook_config_cam_get(
|
||||
struct camhook_config_cam *config_cam,
|
||||
struct cconfig *config,
|
||||
size_t num_cams)
|
||||
{
|
||||
config_cam->num_devices = num_cams;
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY,
|
||||
&config_cam->disable_emu,
|
||||
CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
CAMHOOK_CONFIG_CAM_DISABLE_EMU_KEY,
|
||||
CAMHOOK_CONFIG_CAM_DEFAULT_DISABLE_EMU_VALUE);
|
||||
}
|
||||
for (size_t i = 0; i < num_cams; ++i) {
|
||||
if (!cconfig_util_get_str(
|
||||
config,
|
||||
camhook_config_device_id_keys[i],
|
||||
config_cam->device_id[i],
|
||||
sizeof(config_cam->device_id[i]) - 1,
|
||||
camhook_config_device_default_values[i])) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%s'",
|
||||
camhook_config_device_id_keys[i],
|
||||
camhook_config_device_default_values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/main/camhook/config-cam.h
Normal file
23
src/main/camhook/config-cam.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef CAMHOOK_CONFIG_CAM_H
|
||||
#define CAMHOOK_CONFIG_CAM_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
#define CAMHOOK_CONFIG_CAM_MAX 2
|
||||
|
||||
struct camhook_config_cam {
|
||||
bool disable_emu;
|
||||
size_t num_devices;
|
||||
char device_id[CAMHOOK_CONFIG_CAM_MAX][MAX_PATH];
|
||||
};
|
||||
|
||||
void camhook_config_cam_init(struct cconfig *config, size_t num_cams);
|
||||
|
||||
void camhook_config_cam_get(
|
||||
struct camhook_config_cam *config_cam,
|
||||
struct cconfig *config,
|
||||
size_t num_cams);
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@ libs_cconfig := \
|
||||
util \
|
||||
|
||||
src_cconfig := \
|
||||
cconfig-main.c \
|
||||
cconfig-hook.c \
|
||||
cconfig-util.c \
|
||||
cconfig.c \
|
||||
|
||||
@@ -1,96 +1,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
#include "cconfig/cmd.h"
|
||||
#include "cconfig/conf.h"
|
||||
|
||||
#include "cconfig/cconfig-hook.h"
|
||||
#include "cconfig/cconfig-main.h"
|
||||
|
||||
#include "util/cmdline.h"
|
||||
#include "util/log.h"
|
||||
|
||||
bool cconfig_hook_config_init(struct cconfig* config, const char* usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out)
|
||||
bool cconfig_hook_config_init(
|
||||
struct cconfig *config,
|
||||
const char *usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out)
|
||||
{
|
||||
bool success;
|
||||
int argc;
|
||||
char **argv;
|
||||
enum cconfig_conf_error conf_error;
|
||||
char* config_path;
|
||||
|
||||
success = true;
|
||||
|
||||
args_recover(&argc, &argv);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
|
||||
goto failure_usage;
|
||||
}
|
||||
}
|
||||
|
||||
config_path = NULL;
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--config")) {
|
||||
if (i + 1 >= argc) {
|
||||
log_fatal("--config parameter not followed by a config file "
|
||||
"path param");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
config_path = argv[i + 1];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (config_path) {
|
||||
log_misc("Loading config file: %s", config_path);
|
||||
conf_error = cconfig_conf_load_from_file(config, config_path, false);
|
||||
|
||||
if (conf_error == CCONFIG_CONF_ERROR_NO_SUCH_FILE) {
|
||||
/* Create default config */
|
||||
if (cconfig_conf_save_to_file(config, config_path) !=
|
||||
CCONFIG_CONF_SUCCESS) {
|
||||
log_fatal("Creating default config file '%s' failed",
|
||||
config_path);
|
||||
goto failure;
|
||||
} else {
|
||||
log_info("Default configuration '%s' created. Restart "
|
||||
"application", config_path);
|
||||
goto failure;
|
||||
}
|
||||
} else if (conf_error != CCONFIG_CONF_SUCCESS) {
|
||||
log_fatal("Error loading config file '%s': %d", config_path,
|
||||
conf_error);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
log_misc("Config state after file loading:");
|
||||
cconfig_util_log(config, log_impl_misc);
|
||||
}
|
||||
|
||||
log_misc("Parsing override config parameters from cmd");
|
||||
|
||||
/* Override defaults or values loaded from file with values from cmd */
|
||||
if (!cconfig_cmd_parse(config, "-p", argc, argv, false)) {
|
||||
log_fatal("Error parsing cmd args for config values");
|
||||
goto failure_usage;
|
||||
}
|
||||
|
||||
log_misc("Config state after cmd parameter overrides:");
|
||||
cconfig_util_log(config, log_impl_misc);
|
||||
|
||||
goto success;
|
||||
|
||||
failure_usage:
|
||||
cconfig_cmd_print_usage(config, usage_header, cmd_usage_out);
|
||||
|
||||
failure:
|
||||
success = false;
|
||||
|
||||
success:
|
||||
args_free(argc, argv);
|
||||
|
||||
return success;
|
||||
}
|
||||
return cconfig_main_config_init(config, "--config", NULL, "--help", "-h", usage_header, cmd_usage_out);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
#include "cconfig/cconfig.h"
|
||||
#include "cconfig/cmd.h"
|
||||
|
||||
bool cconfig_hook_config_init(struct cconfig* config, const char* usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out);
|
||||
/**
|
||||
* Init function for cconfig for hooks
|
||||
*
|
||||
* calls cconfig_main_config_init with some defaults for hook dlls
|
||||
* see: cconfig_main_config_init for more details
|
||||
*/
|
||||
bool cconfig_hook_config_init(
|
||||
struct cconfig *config,
|
||||
const char *usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
112
src/main/cconfig/cconfig-main.c
Normal file
112
src/main/cconfig/cconfig-main.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "cconfig/cconfig-util.h"
|
||||
#include "cconfig/cmd.h"
|
||||
#include "cconfig/conf.h"
|
||||
|
||||
#include "cconfig/cconfig-main.h"
|
||||
|
||||
#include "util/cmdline.h"
|
||||
#include "util/log.h"
|
||||
|
||||
bool cconfig_main_config_init(
|
||||
struct cconfig *config,
|
||||
const char *config_parameter_name,
|
||||
const char *default_config_path,
|
||||
const char *help_parameter_name,
|
||||
const char *help_parameter_short_name,
|
||||
const char *usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out)
|
||||
{
|
||||
bool success;
|
||||
int argc;
|
||||
char **argv;
|
||||
enum cconfig_conf_error conf_error;
|
||||
const char *config_path;
|
||||
|
||||
success = true;
|
||||
|
||||
args_recover(&argc, &argv);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], help_parameter_short_name) || !strcmp(argv[i], help_parameter_name)) {
|
||||
goto failure_usage;
|
||||
}
|
||||
}
|
||||
|
||||
config_path = NULL;
|
||||
|
||||
if (config_parameter_name != NULL) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], config_parameter_name)) {
|
||||
if (i + 1 >= argc) {
|
||||
log_fatal(
|
||||
"--config parameter not followed by a config file "
|
||||
"path param");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
config_path = argv[i + 1];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config_path == NULL && default_config_path != NULL) {
|
||||
log_misc("Using default config path: %s", default_config_path);
|
||||
config_path = default_config_path;
|
||||
}
|
||||
|
||||
if (config_path) {
|
||||
log_misc("Loading config file: %s", config_path);
|
||||
conf_error = cconfig_conf_load_from_file(config, config_path, false);
|
||||
|
||||
if (conf_error == CCONFIG_CONF_ERROR_NO_SUCH_FILE) {
|
||||
/* Create default config */
|
||||
if (cconfig_conf_save_to_file(config, config_path) !=
|
||||
CCONFIG_CONF_SUCCESS) {
|
||||
log_fatal(
|
||||
"Creating default config file '%s' failed", config_path);
|
||||
goto failure;
|
||||
} else {
|
||||
log_info(
|
||||
"Default configuration '%s' created. Restart "
|
||||
"application",
|
||||
config_path);
|
||||
goto failure;
|
||||
}
|
||||
} else if (conf_error != CCONFIG_CONF_SUCCESS) {
|
||||
log_fatal(
|
||||
"Error loading config file '%s': %d", config_path, conf_error);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
log_misc("Config state after file loading:");
|
||||
cconfig_util_log(config, log_impl_misc);
|
||||
}
|
||||
|
||||
log_misc("Parsing override config parameters from cmd");
|
||||
|
||||
/* Override defaults or values loaded from file with values from cmd */
|
||||
if (!cconfig_cmd_parse(config, "-p", argc, argv, false)) {
|
||||
log_fatal("Error parsing cmd args for config values");
|
||||
goto failure_usage;
|
||||
}
|
||||
|
||||
log_misc("Config state after cmd parameter overrides:");
|
||||
cconfig_util_log(config, log_impl_misc);
|
||||
|
||||
goto success;
|
||||
|
||||
failure_usage:
|
||||
cconfig_cmd_print_usage(config, usage_header, cmd_usage_out);
|
||||
|
||||
failure:
|
||||
success = false;
|
||||
|
||||
success:
|
||||
args_free(argc, argv);
|
||||
|
||||
return success;
|
||||
}
|
||||
22
src/main/cconfig/cconfig-main.h
Normal file
22
src/main/cconfig/cconfig-main.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef CCONFIG_MAIN_H
|
||||
#define CCONFIG_MAIN_H
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
#include "cconfig/cmd.h"
|
||||
|
||||
/**
|
||||
* Init function for cconfig after all cconfig_util_set's have been called
|
||||
*
|
||||
* will parse a config file first (if specified)
|
||||
* then uses override config parameters from cmd
|
||||
*/
|
||||
bool cconfig_main_config_init(
|
||||
struct cconfig *config,
|
||||
const char *config_cmd_param_name,
|
||||
const char *config_default_path,
|
||||
const char *help_cmd_param_name,
|
||||
const char *help_cmd_param_shortname,
|
||||
const char *usage_header,
|
||||
enum cconfig_cmd_usage_out cmd_usage_out);
|
||||
|
||||
#endif
|
||||
@@ -9,10 +9,13 @@
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
bool cconfig_util_get_int(struct cconfig* config, const char* key, int32_t* ret,
|
||||
int32_t default_value)
|
||||
bool cconfig_util_get_int(
|
||||
struct cconfig *config,
|
||||
const char *key,
|
||||
int32_t *ret,
|
||||
int32_t default_value)
|
||||
{
|
||||
struct cconfig_entry* entry;
|
||||
struct cconfig_entry *entry;
|
||||
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -29,10 +32,10 @@ bool cconfig_util_get_int(struct cconfig* config, const char* key, int32_t* ret,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cconfig_util_get_float(struct cconfig* config, const char* key, float* ret,
|
||||
float default_value)
|
||||
bool cconfig_util_get_float(
|
||||
struct cconfig *config, const char *key, float *ret, float default_value)
|
||||
{
|
||||
struct cconfig_entry* entry;
|
||||
struct cconfig_entry *entry;
|
||||
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -49,10 +52,10 @@ bool cconfig_util_get_float(struct cconfig* config, const char* key, float* ret,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cconfig_util_get_bool(struct cconfig* config, const char* key, bool* ret,
|
||||
bool default_value)
|
||||
bool cconfig_util_get_bool(
|
||||
struct cconfig *config, const char *key, bool *ret, bool default_value)
|
||||
{
|
||||
struct cconfig_entry* entry;
|
||||
struct cconfig_entry *entry;
|
||||
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -73,10 +76,14 @@ bool cconfig_util_get_bool(struct cconfig* config, const char* key, bool* ret,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cconfig_util_get_str(struct cconfig* config, const char* key,
|
||||
char* buffer, size_t len, const char* default_value)
|
||||
bool cconfig_util_get_str(
|
||||
struct cconfig *config,
|
||||
const char *key,
|
||||
char *buffer,
|
||||
size_t len,
|
||||
const char *default_value)
|
||||
{
|
||||
struct cconfig_entry* entry;
|
||||
struct cconfig_entry *entry;
|
||||
size_t str_len;
|
||||
|
||||
log_assert(config);
|
||||
@@ -97,11 +104,15 @@ bool cconfig_util_get_str(struct cconfig* config, const char* key,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cconfig_util_get_data(struct cconfig* config, const char* key,
|
||||
uint8_t* buffer, size_t len, const uint8_t* default_value)
|
||||
bool cconfig_util_get_data(
|
||||
struct cconfig *config,
|
||||
const char *key,
|
||||
uint8_t *buffer,
|
||||
size_t len,
|
||||
const uint8_t *default_value)
|
||||
{
|
||||
size_t res_len;
|
||||
struct cconfig_entry* entry;
|
||||
struct cconfig_entry *entry;
|
||||
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -124,10 +135,10 @@ bool cconfig_util_get_data(struct cconfig* config, const char* key,
|
||||
return false;
|
||||
}
|
||||
|
||||
void cconfig_util_set_int(struct cconfig* config, const char* key,
|
||||
int32_t value, const char* desc)
|
||||
void cconfig_util_set_int(
|
||||
struct cconfig *config, const char *key, int32_t value, const char *desc)
|
||||
{
|
||||
char* str;
|
||||
char *str;
|
||||
size_t str_len;
|
||||
|
||||
log_assert(config);
|
||||
@@ -143,10 +154,10 @@ void cconfig_util_set_int(struct cconfig* config, const char* key,
|
||||
free(str);
|
||||
}
|
||||
|
||||
void cconfig_util_set_float(struct cconfig* config, const char* key,
|
||||
float value, const char* desc)
|
||||
void cconfig_util_set_float(
|
||||
struct cconfig *config, const char *key, float value, const char *desc)
|
||||
{
|
||||
char* str;
|
||||
char *str;
|
||||
size_t str_len;
|
||||
|
||||
log_assert(config);
|
||||
@@ -162,8 +173,8 @@ void cconfig_util_set_float(struct cconfig* config, const char* key,
|
||||
free(str);
|
||||
}
|
||||
|
||||
void cconfig_util_set_bool(struct cconfig* config, const char* key, bool value,
|
||||
const char* desc)
|
||||
void cconfig_util_set_bool(
|
||||
struct cconfig *config, const char *key, bool value, const char *desc)
|
||||
{
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -172,8 +183,11 @@ void cconfig_util_set_bool(struct cconfig* config, const char* key, bool value,
|
||||
cconfig_set(config, key, value ? "true" : "false", desc);
|
||||
}
|
||||
|
||||
void cconfig_util_set_str(struct cconfig* config, const char* key,
|
||||
const char* value, const char* desc)
|
||||
void cconfig_util_set_str(
|
||||
struct cconfig *config,
|
||||
const char *key,
|
||||
const char *value,
|
||||
const char *desc)
|
||||
{
|
||||
log_assert(config);
|
||||
log_assert(key);
|
||||
@@ -183,10 +197,14 @@ void cconfig_util_set_str(struct cconfig* config, const char* key,
|
||||
cconfig_set(config, key, value, desc);
|
||||
}
|
||||
|
||||
void cconfig_util_set_data(struct cconfig* config, const char* key,
|
||||
const uint8_t* value, size_t len, const char* desc)
|
||||
void cconfig_util_set_data(
|
||||
struct cconfig *config,
|
||||
const char *key,
|
||||
const uint8_t *value,
|
||||
size_t len,
|
||||
const char *desc)
|
||||
{
|
||||
char* str;
|
||||
char *str;
|
||||
size_t str_len;
|
||||
|
||||
log_assert(config);
|
||||
@@ -202,10 +220,13 @@ void cconfig_util_set_data(struct cconfig* config, const char* key,
|
||||
free(str);
|
||||
}
|
||||
|
||||
void cconfig_util_log(struct cconfig* config, log_formatter_t log_formatter)
|
||||
void cconfig_util_log(struct cconfig *config, log_formatter_t log_formatter)
|
||||
{
|
||||
for (uint32_t i = 0; i < config->nentries; i++) {
|
||||
log_formatter(LOG_MODULE, "%s=%s", config->entries[i].key,
|
||||
log_formatter(
|
||||
LOG_MODULE,
|
||||
"%s=%s",
|
||||
config->entries[i].key,
|
||||
config->entries[i].value);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user