mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-15 03:45:09 -05:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a80083af2 | ||
|
|
66e0467ad3 | ||
|
|
c5f0116294 | ||
|
|
ddfa814387 | ||
|
|
088d4bf338 | ||
|
|
f1a7621e2b | ||
|
|
4a3d5fa189 | ||
|
|
0f2828da40 | ||
|
|
ba2016b5bc | ||
|
|
b42c9aa93b | ||
|
|
8de259c639 | ||
|
|
0d54587787 | ||
|
|
4721ba2d3c | ||
|
|
1105a2a130 | ||
|
|
8ab92872ad | ||
|
|
a16dc82cef | ||
|
|
729f5abcc0 | ||
|
|
6e0e5031ac | ||
|
|
f17e8d6739 | ||
|
|
ac02609948 | ||
|
|
c644db03ae | ||
|
|
7d5398b6af | ||
|
|
cac09f8f87 | ||
|
|
85c9c444f1 | ||
|
|
8f2ce1f1b3 | ||
|
|
d3bf381a4f | ||
|
|
3acbc7f251 | ||
|
|
839903ab48 | ||
|
|
c929141e71 | ||
|
|
1477480836 | ||
|
|
bf4322e855 | ||
|
|
3eed0a4ab3 | ||
|
|
a9ade9d9d4 | ||
|
|
26336805d2 | ||
|
|
7d0e916b9f | ||
|
|
a03a5604ec | ||
|
|
54e7d783ef | ||
|
|
4ea1397af2 | ||
|
|
fb593df4a1 | ||
|
|
f0c33663e9 | ||
|
|
87ee37d059 | ||
|
|
5688fb7319 | ||
|
|
d529ee484f | ||
|
|
7c43fb7163 | ||
|
|
652d2ef633 | ||
|
|
78884aebad | ||
|
|
549f00bfb3 | ||
|
|
aab45f145f | ||
|
|
6171f0dc60 | ||
|
|
2f05760f4e | ||
|
|
7b5e4772ea | ||
|
|
e266aed1f9 | ||
|
|
0b0e7faef0 | ||
|
|
53866130cb | ||
|
|
dbb8c45a9f | ||
|
|
8ed7d6db71 | ||
|
|
4c746df6a8 | ||
|
|
7d485e7c7e | ||
|
|
deb6e5cf77 | ||
|
|
2a03690772 | ||
|
|
6ce4cce500 | ||
|
|
c6e59bae9b | ||
|
|
31e15ec5ea | ||
|
|
9cef7c03d0 | ||
|
|
f9b37c7a72 | ||
|
|
609c19b0ca | ||
|
|
75b27d5992 | ||
|
|
965df98093 | ||
|
|
0c06d224cc | ||
|
|
fb3d2ea312 | ||
|
|
089253a537 | ||
|
|
a4436747de | ||
|
|
43b11c8778 | ||
|
|
dd7fd860b5 | ||
|
|
18842a1dd3 | ||
|
|
18f6d9ef70 | ||
|
|
592967e191 | ||
|
|
6614cc801e | ||
|
|
8e1151ac02 | ||
|
|
4b60cb6c6c | ||
|
|
770bae4169 | ||
|
|
49d0bc638b | ||
|
|
837affc66c | ||
|
|
ec76ba075f | ||
|
|
f438f04f2a | ||
|
|
865980991e |
147
.gitlab-ci.yml
147
.gitlab-ci.yml
@@ -1,67 +1,136 @@
|
|||||||
|
#
|
||||||
|
# This pipeline requires packages to be switched on under the repository settings. Otherwise, you will 403s when
|
||||||
|
# uploading to the package repo is triggered.
|
||||||
|
#
|
||||||
|
# Variables to setup in GitLab CI/CD settings of the project
|
||||||
|
#
|
||||||
|
# The variables with BASE64 postfixes need to contain the base64 encoded data. Otherwise, masking
|
||||||
|
# in GitLab won't work due to not matching their pre-defined regex
|
||||||
|
#
|
||||||
|
# CI_PIGSTALL_DATA_PREFIX_BASE64
|
||||||
|
# CI_PIGSTALL_LINK_BASE64
|
||||||
|
# CI_PIGSTALL_PHP_SESSION_ID
|
||||||
|
# CI_PIGSTALL_SESSION_BASE64
|
||||||
|
#
|
||||||
|
# CI_TOOLS_UPLOAD_KEY
|
||||||
|
# CI_TOOLS_UPLOAD_URL
|
||||||
|
# CI_TOOLS_URL
|
||||||
|
|
||||||
image: docker:stable
|
image: docker:stable
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
DOCKER_TLS_CERTDIR: "/certs"
|
DOCKER_TLS_CERTDIR: "/certs"
|
||||||
|
DIST_PACKAGE_RELATIVE_PATH: "build/docker/bemanitools.zip"
|
||||||
|
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/bemanitools"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker:19.03.8-dind
|
- docker:19.03.8-dind
|
||||||
|
|
||||||
before_script:
|
|
||||||
- docker info
|
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- create-release-package
|
- upload
|
||||||
- releasetag
|
- release
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
only:
|
||||||
|
refs:
|
||||||
|
- master
|
||||||
|
- tags
|
||||||
before_script:
|
before_script:
|
||||||
- apk update && apk add make > /dev/null
|
- apk update && apk add make > /dev/null
|
||||||
script:
|
script:
|
||||||
- make build-docker
|
- make build-docker
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
|
||||||
paths:
|
paths:
|
||||||
- build
|
- build
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
|
upload-package-registry:
|
||||||
|
stage: upload
|
||||||
|
image: curlimages/curl:latest
|
||||||
only:
|
only:
|
||||||
refs:
|
refs:
|
||||||
- master
|
- master
|
||||||
|
- tags
|
||||||
create-release-package:
|
|
||||||
stage: create-release-package
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- build
|
- build
|
||||||
before_script:
|
|
||||||
- apk update && apk add zip > /dev/null
|
|
||||||
script:
|
|
||||||
- mv build/docker/bemanitools.zip ./bemanitools.zip
|
|
||||||
- rm -r build
|
|
||||||
- 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:
|
|
||||||
- apk update && apk add curl > /dev/null
|
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
curl --silent --show-error \
|
if [ "${CI_COMMIT_TAG}" ]; then
|
||||||
--data "{\"tag_name\": \"${CI_COMMIT_TAG}\", \"name\": \"${CI_PROJECT_NAME}-${CI_COMMIT_TAG}\", \"description\": \"${CI_COMMIT_TAG_MESSAGE:-No release notes.}\"}" \
|
version="${CI_COMMIT_TAG}"
|
||||||
--header "Content-Type: application/json" \
|
else
|
||||||
--header "Private-Token: ${CI_PRIVATE_TOKEN}" \
|
version="${CI_COMMIT_SHORT_SHA}"
|
||||||
--request POST \
|
fi
|
||||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/releases"
|
- |
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--fail \
|
||||||
|
--show-error \
|
||||||
|
--header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
|
||||||
|
--upload-file "${DIST_PACKAGE_RELATIVE_PATH}" \
|
||||||
|
$PACKAGE_REGISTRY_URL/${version}/bemanitools.zip
|
||||||
|
|
||||||
|
upload-tools-page:
|
||||||
|
stage: upload
|
||||||
|
image: curlimages/curl:latest
|
||||||
only:
|
only:
|
||||||
- tags
|
refs:
|
||||||
|
- tags
|
||||||
|
dependencies:
|
||||||
|
- build
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--fail \
|
||||||
|
--show-error \
|
||||||
|
--connect-timeout 5 \
|
||||||
|
--max-time 10 \
|
||||||
|
--retry 5 \
|
||||||
|
-F "key=${CI_TOOLS_UPLOAD_KEY}" \
|
||||||
|
-F "filename=${CI_PROJECT_NAME}-v${CI_COMMIT_TAG}.zip" \
|
||||||
|
-F "file=@${DIST_PACKAGE_RELATIVE_PATH}" \
|
||||||
|
${CI_TOOLS_UPLOAD_URL}
|
||||||
|
|
||||||
|
release-gitlab:
|
||||||
|
stage: release
|
||||||
|
image: registry.gitlab.com/gitlab-org/release-cli:v0.8.0
|
||||||
|
only:
|
||||||
|
refs:
|
||||||
|
- tags
|
||||||
|
script:
|
||||||
|
- version="$CI_COMMIT_TAG"
|
||||||
|
- release_message="$(scripts/ci/create-release-message.sh "${version}" < CHANGELOG.md)"
|
||||||
|
- |
|
||||||
|
release-cli create \
|
||||||
|
--name "bemanitools ${version}" \
|
||||||
|
--description="${release_message}" \
|
||||||
|
--tag-name ${version} \
|
||||||
|
--assets-link "{\"name\":\"Distribution binaries\",\"url\":\"${PACKAGE_REGISTRY_URL}/${version}/bemanitools.zip\"}"
|
||||||
|
|
||||||
|
release-pigstall:
|
||||||
|
stage: release
|
||||||
|
image: curlimages/curl:latest
|
||||||
|
only:
|
||||||
|
refs:
|
||||||
|
- tags
|
||||||
|
script:
|
||||||
|
- version="${CI_COMMIT_TAG}"
|
||||||
|
- changelog_excerpt="$(scripts/ci/create-release-message.sh "${version}" < CHANGELOG.md)"
|
||||||
|
- release_message="$(printf "bemanitools ${version} released\n${CI_TOOLS_URL}/bemanitools-v${version}.zip\n${changelog_excerpt}")"
|
||||||
|
- session="$(echo "$CI_PIGSTALL_SESSION_BASE64" | base64 -d)"
|
||||||
|
- data_prefix="$(echo "$CI_PIGSTALL_DATA_PREFIX_BASE64" | base64 -d)"
|
||||||
|
- link="$(echo "$CI_PIGSTALL_LINK_BASE64" | base64 -d)"
|
||||||
|
- |
|
||||||
|
curl \
|
||||||
|
--silent \
|
||||||
|
--fail \
|
||||||
|
--connect-timeout 5 \
|
||||||
|
--max-time 10 \
|
||||||
|
--retry 5 \
|
||||||
|
--show-error \
|
||||||
|
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||||
|
-H "Cookie: PHPSESSID=$CI_PIGSTALL_PHP_SESSION_ID; session=${session}" \
|
||||||
|
--data-raw "${data_prefix}&body=${release_message}" \
|
||||||
|
"${link}"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
necessary -->
|
necessary -->
|
||||||
|
|
||||||
## Steps to reproduce
|
## Steps to reproduce
|
||||||
|
<!-- Try running the game with a default configuration as well. If that also causes issues, please point that out here in the report. This might speed up the debugging process.-->
|
||||||
|
|
||||||
<!--- Provide a detailed step by step description how to reproduce this issue -->
|
<!--- Provide a detailed step by step description how to reproduce this issue -->
|
||||||
1.
|
1.
|
||||||
2.
|
2.
|
||||||
|
|||||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,4 +1,25 @@
|
|||||||
# Release history
|
# Release history
|
||||||
|
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
|
||||||
|
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
|
||||||
|
|
||||||
|
## 5.37
|
||||||
|
* jbhook1: Support jubeat (1) and ripples
|
||||||
|
* jbhook2: Support jubeat knit and copious
|
||||||
|
* jbhook3: Support jubeat saucer, prop, qubell, clan and festo
|
||||||
|
|
||||||
|
## 5.36
|
||||||
|
* iidxhook9: Support for IIDX28
|
||||||
|
* Various bugfixes
|
||||||
|
|
||||||
|
## 5.35
|
||||||
|
* Jubeat: Add jbio-p4io
|
||||||
|
* Nostalgia: Add nostio-panb
|
||||||
|
* Misc: Add wavepass support to aciodrv-icca (and eamio-icca)
|
||||||
|
* Misc: Refactor aciodrv to support multiple devices using the same port (with aciomgr)
|
||||||
|
* Misc: Fix d3d9ex windowed hook not behaving correctly (size/framed)
|
||||||
|
* Misc: Fix docs not being included with release
|
||||||
|
* Various bugfixes
|
||||||
|
|
||||||
## 5.34
|
## 5.34
|
||||||
* IIDX: Support IO and card reader feature switches to disable emulation in iidxhook4-7
|
* IIDX: Support IO and card reader feature switches to disable emulation in iidxhook4-7
|
||||||
* Jubeat: jbio implementation for magicbox hardware
|
* Jubeat: jbio implementation for magicbox hardware
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
|
|||||||
$(V)echo ... $$(dll_$1_$2_$3)
|
$(V)echo ... $$(dll_$1_$2_$3)
|
||||||
$(V)$$(toolchain_$1)gcc -shared \
|
$(V)$$(toolchain_$1)gcc -shared \
|
||||||
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
|
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
|
||||||
$$^ $$(ldflags_$3)
|
-Wl,--start-group $$^ -Wl,--end-group $$(ldflags_$3)
|
||||||
$(V)$$(toolchain_$1)strip $$(dll_$1_$2_$3)
|
$(V)$$(toolchain_$1)strip $$(dll_$1_$2_$3)
|
||||||
$(V)$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
|
$(V)$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
|
||||||
|
|
||||||
|
|||||||
98
Module.mk
98
Module.mk
@@ -26,7 +26,8 @@
|
|||||||
# 8: Patch 3: beatmania IIDX 16 Empress
|
# 8: Patch 3: beatmania IIDX 16 Empress
|
||||||
# jubeat
|
# jubeat
|
||||||
#
|
#
|
||||||
# 10: Patch 4: DanceDanceRevolution X2
|
# 10: Patch 2: jubeat Knit
|
||||||
|
# Patch 4: DanceDanceRevolution X2
|
||||||
#
|
#
|
||||||
# 11: Patch 1: beatmania IIDX 18 Resort Anthem
|
# 11: Patch 1: beatmania IIDX 18 Resort Anthem
|
||||||
# pop'n music 19 Tune Street
|
# pop'n music 19 Tune Street
|
||||||
@@ -71,13 +72,15 @@ cflags += \
|
|||||||
# Each AVS-dependent project should consume the earliest AVS import definition
|
# Each AVS-dependent project should consume the earliest AVS import definition
|
||||||
# that is still ABI-compatible with the real build its target links against.
|
# that is still ABI-compatible with the real build its target links against.
|
||||||
|
|
||||||
avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 803 0
|
avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 1002 803 0
|
||||||
avsvers_64 := 1700 1603 1601 1508
|
avsvers_64 := 1700 1603 1601 1509 1508
|
||||||
|
|
||||||
imps += avs avs-ea3
|
imps += avs avs-ea3
|
||||||
|
|
||||||
include src/main/aciodrv/Module.mk
|
include src/main/aciodrv/Module.mk
|
||||||
|
include src/main/aciodrv-proc/Module.mk
|
||||||
include src/main/acioemu/Module.mk
|
include src/main/acioemu/Module.mk
|
||||||
|
include src/main/aciomgr/Module.mk
|
||||||
include src/main/aciotest/Module.mk
|
include src/main/aciotest/Module.mk
|
||||||
include src/main/asio/Module.mk
|
include src/main/asio/Module.mk
|
||||||
include src/main/bio2drv/Module.mk
|
include src/main/bio2drv/Module.mk
|
||||||
@@ -89,6 +92,7 @@ include src/main/camhook/Module.mk
|
|||||||
include src/main/cconfig/Module.mk
|
include src/main/cconfig/Module.mk
|
||||||
include src/main/config/Module.mk
|
include src/main/config/Module.mk
|
||||||
include src/main/d3d9exhook/Module.mk
|
include src/main/d3d9exhook/Module.mk
|
||||||
|
include src/main/ddrhook-util/Module.mk
|
||||||
include src/main/ddrhook/Module.mk
|
include src/main/ddrhook/Module.mk
|
||||||
include src/main/ddrio-mm/Module.mk
|
include src/main/ddrio-mm/Module.mk
|
||||||
include src/main/ddrio-smx/Module.mk
|
include src/main/ddrio-smx/Module.mk
|
||||||
@@ -133,16 +137,20 @@ include src/main/iidxio-ezusb2/Module.mk
|
|||||||
include src/main/iidxio/Module.mk
|
include src/main/iidxio/Module.mk
|
||||||
include src/main/iidxiotest/Module.mk
|
include src/main/iidxiotest/Module.mk
|
||||||
include src/main/inject/Module.mk
|
include src/main/inject/Module.mk
|
||||||
include src/main/jbhook/Module.mk
|
|
||||||
include src/main/jbhook1/Module.mk
|
|
||||||
include src/main/jbio-magicbox/Module.mk
|
include src/main/jbio-magicbox/Module.mk
|
||||||
|
include src/main/jbio-p4io/Module.mk
|
||||||
include src/main/jbio/Module.mk
|
include src/main/jbio/Module.mk
|
||||||
include src/main/jbiotest/Module.mk
|
include src/main/jbiotest/Module.mk
|
||||||
|
include src/main/jbhook-util/Module.mk
|
||||||
|
include src/main/jbhook1/Module.mk
|
||||||
|
include src/main/jbhook2/Module.mk
|
||||||
|
include src/main/jbhook3/Module.mk
|
||||||
include src/main/launcher/Module.mk
|
include src/main/launcher/Module.mk
|
||||||
include src/main/mempatch-hook/Module.mk
|
include src/main/mempatch-hook/Module.mk
|
||||||
include src/main/mm/Module.mk
|
include src/main/mm/Module.mk
|
||||||
include src/main/p3io/Module.mk
|
include src/main/p3io/Module.mk
|
||||||
include src/main/p3ioemu/Module.mk
|
include src/main/p3ioemu/Module.mk
|
||||||
|
include src/main/p4iodrv/Module.mk
|
||||||
include src/main/p4ioemu/Module.mk
|
include src/main/p4ioemu/Module.mk
|
||||||
include src/main/pcbidgen/Module.mk
|
include src/main/pcbidgen/Module.mk
|
||||||
include src/main/sdvxhook/Module.mk
|
include src/main/sdvxhook/Module.mk
|
||||||
@@ -361,7 +369,7 @@ $(zipdir)/iidx-25-to-26.zip: \
|
|||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/iidx-27.zip: \
|
$(zipdir)/iidx-27-to-28.zip: \
|
||||||
build/bin/avs2_1700-64/iidxhook9.dll \
|
build/bin/avs2_1700-64/iidxhook9.dll \
|
||||||
build/bin/avs2_1700-64/launcher.exe \
|
build/bin/avs2_1700-64/launcher.exe \
|
||||||
build/bin/indep-64/config.exe \
|
build/bin/indep-64/config.exe \
|
||||||
@@ -371,13 +379,16 @@ $(zipdir)/iidx-27.zip: \
|
|||||||
build/bin/indep-64/vefxio.dll \
|
build/bin/indep-64/vefxio.dll \
|
||||||
dist/iidx/config.bat \
|
dist/iidx/config.bat \
|
||||||
dist/iidx/gamestart-27.bat \
|
dist/iidx/gamestart-27.bat \
|
||||||
|
dist/iidx/gamestart-28.bat \
|
||||||
dist/iidx/iidxhook-27.conf \
|
dist/iidx/iidxhook-27.conf \
|
||||||
|
dist/iidx/iidxhook-28.conf \
|
||||||
dist/iidx/vefx.txt \
|
dist/iidx/vefx.txt \
|
||||||
| $(zipdir)/
|
| $(zipdir)/
|
||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/iidx-hwio-x86.zip: \
|
$(zipdir)/iidx-hwio-x86.zip: \
|
||||||
|
build/bin/indep-32/aciomgr.dll \
|
||||||
build/bin/indep-32/eamio-icca.dll \
|
build/bin/indep-32/eamio-icca.dll \
|
||||||
build/bin/indep-32/iidxio-bio2.dll \
|
build/bin/indep-32/iidxio-bio2.dll \
|
||||||
build/bin/indep-32/iidxio-ezusb.dll \
|
build/bin/indep-32/iidxio-ezusb.dll \
|
||||||
@@ -390,6 +401,7 @@ $(zipdir)/iidx-hwio-x86.zip: \
|
|||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/iidx-hwio-x64.zip: \
|
$(zipdir)/iidx-hwio-x64.zip: \
|
||||||
|
build/bin/indep-64/aciomgr.dll \
|
||||||
build/bin/indep-64/eamio-icca.dll \
|
build/bin/indep-64/eamio-icca.dll \
|
||||||
build/bin/indep-64/iidxio-bio2.dll \
|
build/bin/indep-64/iidxio-bio2.dll \
|
||||||
build/bin/indep-64/iidxio-ezusb.dll \
|
build/bin/indep-64/iidxio-ezusb.dll \
|
||||||
@@ -415,28 +427,79 @@ $(zipdir)/jb-01.zip: \
|
|||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
|
$(zipdir)/jb-02.zip: \
|
||||||
|
build/bin/avs2_1002-32/jbhook1.dll \
|
||||||
|
build/bin/indep-32/inject.exe \
|
||||||
|
build/bin/indep-32/config.exe \
|
||||||
|
build/bin/indep-32/eamio.dll \
|
||||||
|
build/bin/indep-32/geninput.dll \
|
||||||
|
build/bin/indep-32/jbio.dll \
|
||||||
|
dist/jb/config.bat \
|
||||||
|
dist/jb/gamestart-02.bat \
|
||||||
|
dist/jb/jbhook-02.conf \
|
||||||
|
| $(zipdir)/
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
|
$(zipdir)/jb-03.zip: \
|
||||||
|
build/bin/avs2_1101-32/jbhook2.dll \
|
||||||
|
build/bin/avs2_1101-32/launcher.exe \
|
||||||
|
build/bin/indep-32/config.exe \
|
||||||
|
build/bin/indep-32/eamio.dll \
|
||||||
|
build/bin/indep-32/geninput.dll \
|
||||||
|
build/bin/indep-32/jbio.dll \
|
||||||
|
dist/jb/config.bat \
|
||||||
|
dist/jb/gamestart-03.bat \
|
||||||
|
| $(zipdir)/
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
|
$(zipdir)/jb-04.zip: \
|
||||||
|
build/bin/avs2_1304-32/jbhook2.dll \
|
||||||
|
build/bin/avs2_1304-32/launcher.exe \
|
||||||
|
build/bin/indep-32/config.exe \
|
||||||
|
build/bin/indep-32/eamio.dll \
|
||||||
|
build/bin/indep-32/geninput.dll \
|
||||||
|
build/bin/indep-32/jbio.dll \
|
||||||
|
dist/jb/config.bat \
|
||||||
|
dist/jb/gamestart-03.bat \
|
||||||
|
| $(zipdir)/
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/jb-05-to-07.zip: \
|
$(zipdir)/jb-05-to-07.zip: \
|
||||||
build/bin/avs2_1508-32/jbhook.dll \
|
build/bin/avs2_1508-32/jbhook3.dll \
|
||||||
build/bin/avs2_1508-32/launcher.exe \
|
build/bin/avs2_1508-32/launcher.exe \
|
||||||
build/bin/indep-32/config.exe \
|
build/bin/indep-32/config.exe \
|
||||||
build/bin/indep-32/eamio.dll \
|
build/bin/indep-32/eamio.dll \
|
||||||
build/bin/indep-32/geninput.dll \
|
build/bin/indep-32/geninput.dll \
|
||||||
build/bin/indep-32/jbio.dll \
|
build/bin/indep-32/jbio.dll \
|
||||||
dist/jb/config.bat \
|
dist/jb/config.bat \
|
||||||
dist/jb/gamestart.bat \
|
dist/jb/gamestart-04.bat \
|
||||||
| $(zipdir)/
|
| $(zipdir)/
|
||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/jb-08.zip: \
|
$(zipdir)/jb-08.zip: \
|
||||||
build/bin/avs2_1700-32/jbhook.dll \
|
build/bin/avs2_1700-32/jbhook3.dll \
|
||||||
build/bin/avs2_1700-32/launcher.exe \
|
build/bin/avs2_1700-32/launcher.exe \
|
||||||
build/bin/indep-32/config.exe \
|
build/bin/indep-32/config.exe \
|
||||||
build/bin/indep-32/eamio.dll \
|
build/bin/indep-32/eamio.dll \
|
||||||
build/bin/indep-32/geninput.dll \
|
build/bin/indep-32/geninput.dll \
|
||||||
build/bin/indep-32/jbio.dll \
|
build/bin/indep-32/jbio.dll \
|
||||||
dist/jb/config.bat \
|
dist/jb/config.bat \
|
||||||
dist/jb/gamestart.bat \
|
dist/jb/gamestart-04.bat \
|
||||||
|
| $(zipdir)/
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
|
$(zipdir)/jb-hwio.zip: \
|
||||||
|
build/bin/indep-32/aciomgr.dll \
|
||||||
|
build/bin/indep-32/eamio-icca.dll \
|
||||||
|
build/bin/indep-32/jbio-magicbox.dll \
|
||||||
|
build/bin/indep-32/jbio-p4io.dll \
|
||||||
|
dist/jb/jbio-h44b.conf \
|
||||||
|
dist/jb/eamio-icc.conf \
|
||||||
| $(zipdir)/
|
| $(zipdir)/
|
||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
@@ -483,6 +546,8 @@ $(zipdir)/sdvx-05-cn.zip: \
|
|||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/sdvx-hwio-x86.zip: \
|
$(zipdir)/sdvx-hwio-x86.zip: \
|
||||||
|
build/bin/indep-32/aciomgr.dll \
|
||||||
|
build/bin/indep-32/eamio-icca.dll \
|
||||||
build/bin/indep-32/sdvxio-kfca.dll \
|
build/bin/indep-32/sdvxio-kfca.dll \
|
||||||
build/bin/indep-32/sdvxio-bio2.dll \
|
build/bin/indep-32/sdvxio-bio2.dll \
|
||||||
build/bin/indep-32/vigem-sdvxio.exe \
|
build/bin/indep-32/vigem-sdvxio.exe \
|
||||||
@@ -491,6 +556,8 @@ $(zipdir)/sdvx-hwio-x86.zip: \
|
|||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/sdvx-hwio-x64.zip: \
|
$(zipdir)/sdvx-hwio-x64.zip: \
|
||||||
|
build/bin/indep-64/aciomgr.dll \
|
||||||
|
build/bin/indep-64/eamio-icca.dll \
|
||||||
build/bin/indep-64/sdvxio-kfca.dll \
|
build/bin/indep-64/sdvxio-kfca.dll \
|
||||||
build/bin/indep-64/sdvxio-bio2.dll \
|
build/bin/indep-64/sdvxio-bio2.dll \
|
||||||
build/bin/indep-64/vigem-sdvxio.exe \
|
build/bin/indep-64/vigem-sdvxio.exe \
|
||||||
@@ -549,10 +616,7 @@ $(zipdir)/bst.zip: \
|
|||||||
$(V)zip -j $@ $^
|
$(V)zip -j $@ $^
|
||||||
|
|
||||||
$(zipdir)/doc.zip: \
|
$(zipdir)/doc.zip: \
|
||||||
doc/iidxhook \
|
doc/ \
|
||||||
doc/sdvxhook \
|
|
||||||
doc/jbhook \
|
|
||||||
doc/tools \
|
|
||||||
| $(zipdir)/
|
| $(zipdir)/
|
||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)zip -r $@ $^
|
$(V)zip -r $@ $^
|
||||||
@@ -596,12 +660,16 @@ $(BUILDDIR)/bemanitools.zip: \
|
|||||||
$(zipdir)/iidx-20.zip \
|
$(zipdir)/iidx-20.zip \
|
||||||
$(zipdir)/iidx-21-to-24.zip \
|
$(zipdir)/iidx-21-to-24.zip \
|
||||||
$(zipdir)/iidx-25-to-26.zip \
|
$(zipdir)/iidx-25-to-26.zip \
|
||||||
$(zipdir)/iidx-27.zip \
|
$(zipdir)/iidx-27-to-28.zip \
|
||||||
$(zipdir)/iidx-hwio-x86.zip \
|
$(zipdir)/iidx-hwio-x86.zip \
|
||||||
$(zipdir)/iidx-hwio-x64.zip \
|
$(zipdir)/iidx-hwio-x64.zip \
|
||||||
$(zipdir)/jb-01.zip \
|
$(zipdir)/jb-01.zip \
|
||||||
|
$(zipdir)/jb-02.zip \
|
||||||
|
$(zipdir)/jb-03.zip \
|
||||||
|
$(zipdir)/jb-04.zip \
|
||||||
$(zipdir)/jb-05-to-07.zip \
|
$(zipdir)/jb-05-to-07.zip \
|
||||||
$(zipdir)/jb-08.zip \
|
$(zipdir)/jb-08.zip \
|
||||||
|
$(zipdir)/jb-hwio.zip \
|
||||||
$(zipdir)/sdvx-01-to-04.zip \
|
$(zipdir)/sdvx-01-to-04.zip \
|
||||||
$(zipdir)/sdvx-05.zip \
|
$(zipdir)/sdvx-05.zip \
|
||||||
$(zipdir)/sdvx-05-cn.zip \
|
$(zipdir)/sdvx-05-cn.zip \
|
||||||
|
|||||||
51
README.md
51
README.md
@@ -1,7 +1,7 @@
|
|||||||
# Bemanitools 5
|
# Bemanitools 5
|
||||||
[](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
|
[](https://dev.s-ul.net/djhackers/bemanitools/commits/master)
|
||||||
|
|
||||||
Version: 5.34
|
Version: 5.37
|
||||||
|
|
||||||
[Release history](CHANGELOG.md)
|
[Release history](CHANGELOG.md)
|
||||||
|
|
||||||
@@ -55,13 +55,18 @@ The tl;dr version and golden rules of the sections in the document:
|
|||||||
* Beatmania IIDX 24 SINOBUZ (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 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)
|
* Beatmania IIDX 26 Rootage (iidx-25-to-26.zip) using [iidxhook8](doc/iidxhook/iidxhook8.md)
|
||||||
* Beatmania IIDX 27 Heroic Verse (iidx-27.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
|
* Beatmania IIDX 27 Heroic Verse (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||||
|
* Beatmania IIDX 28 BISTROVER (iidx-27-to-28.zip) using [iidxhook9](doc/iidxhook/iidxhook9.md)
|
||||||
* jubeat
|
* jubeat
|
||||||
* jubeat (experimental/buggy) (jb-01.zip) using [jbhook1](doc/jbhook1/jbhook1.md)
|
* jubeat (jb-01.zip) using [jbhook1](doc/jbhook/jbhook1.md)
|
||||||
* jubeat saucer (fulfill) (jb-05-to-07.zip) using jbhook
|
* jubeat ripples (jb-02.zip) using [jbhook1](doc/jbhook/jbhook1.md)
|
||||||
* jubeat prop (jb-05-to-07.zip) using jbhook
|
* jubeat knit (jb-03.zip) using [jbhook2](doc/jbhook/jbhook2.md)
|
||||||
* jubeat Qubell (jb-05-to-07.zip) using jbhook
|
* jubeat copious (jb-04.zip) using [jbhook2](doc/jbhook/jbhook2.md)
|
||||||
* jubeat clan (jb-08.zip) using jbhook
|
* jubeat saucer (fulfill) (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||||
|
* jubeat prop (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||||
|
* jubeat qubell (jb-05-to-07.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||||
|
* jubeat clan (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||||
|
* jubeat festo (jb-08.zip) using [jbhook3](doc/jbhook/jbhook3.md)
|
||||||
* SOUND VOLTEX
|
* SOUND VOLTEX
|
||||||
* SOUND VOLTEX BOOTH (sdvx-01-to-04.zip) using sdvxhook
|
* SOUND VOLTEX BOOTH (sdvx-01-to-04.zip) using sdvxhook
|
||||||
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
|
* SOUND VOLTEX II -infinite infection- (sdvx-01-to-04.zip) using sdvxhook
|
||||||
@@ -73,7 +78,7 @@ The tl;dr version and golden rules of the sections in the document:
|
|||||||
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that
|
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that
|
||||||
implements BT5 APIs.
|
implements BT5 APIs.
|
||||||
|
|
||||||
See the dedicated [readme](docs/vigem/README.md) for details.
|
See the dedicated [readme](doc/vigem/README.md) for details.
|
||||||
|
|
||||||
## Supported platforms
|
## Supported platforms
|
||||||
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
|
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
|
||||||
@@ -110,6 +115,34 @@ important aspects you should know before you get started with development.
|
|||||||
### API
|
### API
|
||||||
Please refer to the [API documentation](doc/api.md).
|
Please refer to the [API documentation](doc/api.md).
|
||||||
|
|
||||||
|
## Release process
|
||||||
|
Steps for the release process:
|
||||||
|
1. Update the corresponding section in the [changelog](CHANGELOG.md) with bullet points reflecting
|
||||||
|
major features merged into master since the previous release
|
||||||
|
1. Make sure you have the latest `master` state pulled to your local copy
|
||||||
|
1. Tag the release with the next release number which also be found at the
|
||||||
|
[top of the readme](#bemanitools-5) as it always reflects the current version beinged worked on
|
||||||
|
on the `master` branch , e.g. 5.35: `git tag 5.35`
|
||||||
|
1. Push the tag to upstream: `git push origin 5.35`
|
||||||
|
1. The [build pipeline](https://dev.s-ul.net/djhackers/bemanitools/-/pipelines) should start
|
||||||
|
automatically once the tag is pushed including the steps `build` and `upload-release`
|
||||||
|
1. Once completed successfully, the release is uploaded
|
||||||
|
1. Take the changelog of the published version and notify the pigs in the stall about it:
|
||||||
|
1. New post in thread
|
||||||
|
```
|
||||||
|
<insert version here> released: <direct link to published version>
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
<paste changelog here>
|
||||||
|
```
|
||||||
|
1. Update the OP title by bumping the version number in it
|
||||||
|
1. Update the OP post by extending it accordingly (see previous entries)
|
||||||
|
|
||||||
|
1. Bump the version number at the [top of this readme](#bemanitools-5) and add a new empty section
|
||||||
|
in the [changelog](CHANGELOG.md) with the new version number as title. Commit changes and push to
|
||||||
|
`master` branch
|
||||||
|
1. Continue developing and merging MRs until you decide its time for another release
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the
|
Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the
|
||||||
[LICENSE file](LICENSE) included with the source code.
|
[LICENSE file](LICENSE) included with the source code.
|
||||||
|
|||||||
16
dist/iidx/gamestart-28.bat
vendored
Normal file
16
dist/iidx/gamestart-28.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 -B iidxhook9.dll bm2dx.dll --config iidxhook-28.conf %*
|
||||||
8
dist/iidx/iidxhook-27.conf
vendored
8
dist/iidx/iidxhook-27.conf
vendored
@@ -34,7 +34,7 @@ gfx.framed=true
|
|||||||
# Run the game windowed
|
# Run the game windowed
|
||||||
gfx.windowed=false
|
gfx.windowed=false
|
||||||
|
|
||||||
# Confine mouse coursor to window
|
# Confine mouse cursor to window
|
||||||
gfx.confined=false
|
gfx.confined=false
|
||||||
|
|
||||||
# Windowed width, -1 for default size
|
# Windowed width, -1 for default size
|
||||||
@@ -43,6 +43,12 @@ gfx.window_width=-1
|
|||||||
# Windowed height, -1 for default size
|
# Windowed height, -1 for default size
|
||||||
gfx.window_height=-1
|
gfx.window_height=-1
|
||||||
|
|
||||||
|
# Windowed X, -1 for default X position
|
||||||
|
gfx.window_x=-1
|
||||||
|
|
||||||
|
# Windowed Y, -1 for default Y position
|
||||||
|
gfx.window_y=-1
|
||||||
|
|
||||||
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
|
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
|
||||||
gfx.forced_refresh_rate=-1
|
gfx.forced_refresh_rate=-1
|
||||||
|
|
||||||
|
|||||||
78
dist/iidx/iidxhook-28.conf
vendored
Normal file
78
dist/iidx/iidxhook-28.conf
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
# Lightning cab mode (requires additional IO emulation)
|
||||||
|
io.lightning_mode=false
|
||||||
|
|
||||||
|
# Disable camera connection
|
||||||
|
io.disable_cams=true
|
||||||
|
|
||||||
|
# Disables the built in file hooks, requiring manual file creation
|
||||||
|
io.disable_file_hooks=false
|
||||||
|
|
||||||
|
# Turntable sensitivity multiplier (1.0 is default)
|
||||||
|
io.tt_multiplier=1.0
|
||||||
|
|
||||||
|
# Disables the camera emulation
|
||||||
|
cam.disable_emu=true
|
||||||
|
|
||||||
|
# Override camera device ID detection (copy from device manager, do not escape)
|
||||||
|
cam.device_id1=
|
||||||
|
|
||||||
|
# Override camera device ID detection (copy from device manager, do not escape)
|
||||||
|
cam.device_id2=
|
||||||
|
|
||||||
|
# Run the game in a framed window (requires windowed option)
|
||||||
|
gfx.framed=true
|
||||||
|
|
||||||
|
# Run the game windowed
|
||||||
|
gfx.windowed=false
|
||||||
|
|
||||||
|
# Confine mouse cursor to window
|
||||||
|
gfx.confined=false
|
||||||
|
|
||||||
|
# Windowed width, -1 for default size
|
||||||
|
gfx.window_width=-1
|
||||||
|
|
||||||
|
# Windowed height, -1 for default size
|
||||||
|
gfx.window_height=-1
|
||||||
|
|
||||||
|
# Windowed X, -1 for default X position
|
||||||
|
gfx.window_x=-1
|
||||||
|
|
||||||
|
# Windowed Y, -1 for default Y position
|
||||||
|
gfx.window_y=-1
|
||||||
|
|
||||||
|
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
|
||||||
|
gfx.forced_refresh_rate=-1
|
||||||
|
|
||||||
|
# D3D9ex device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||||
|
gfx.device_adapter=-1
|
||||||
|
|
||||||
|
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
|
||||||
|
gfx.force_orientation=-1
|
||||||
|
|
||||||
|
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
|
||||||
|
gfx.force_screen_res.width=-1
|
||||||
|
|
||||||
|
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
|
||||||
|
gfx.force_screen_res.height=-1
|
||||||
|
|
||||||
|
# IP of adapter to force override with
|
||||||
|
adapter.override_ip=
|
||||||
|
|
||||||
|
# Force ASIO audio mode/device (if applicable / TDJ default)
|
||||||
|
asio.force_asio=false
|
||||||
|
|
||||||
|
# Force WASAPI audio mode (if applicable / LDJ default)
|
||||||
|
asio.force_wasapi=true
|
||||||
|
|
||||||
|
# The ASIO device name to use
|
||||||
|
asio.device_name=XONAR SOUND CARD(64)
|
||||||
|
|
||||||
5
dist/jb/eamio-icc.conf
vendored
Normal file
5
dist/jb/eamio-icc.conf
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# ICCA serial port
|
||||||
|
icc.port=COM2
|
||||||
|
|
||||||
|
# ICCA bus baudrate (real devices expect 57600)
|
||||||
|
icc.baud=57600
|
||||||
5
dist/jb/gamestart-02.bat
vendored
Normal file
5
dist/jb/gamestart-02.bat
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
inject jbhook1.dll jubeat.exe --config jbhook-02.conf %*
|
||||||
@@ -7,4 +7,4 @@ if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
|
|||||||
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
|
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
|
||||||
if not exist dev\raw mkdir dev\raw
|
if not exist dev\raw mkdir dev\raw
|
||||||
|
|
||||||
launcher -H 33554432 -K jbhook.dll jubeat.dll
|
launcher -H 33554432 -K jbhook2.dll jubeat.dll
|
||||||
10
dist/jb/gamestart-04.bat
vendored
Normal file
10
dist/jb/gamestart-04.bat
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
if not exist dev\nvram mkdir dev\nvram
|
||||||
|
if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
|
||||||
|
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
|
||||||
|
if not exist dev\raw mkdir dev\raw
|
||||||
|
|
||||||
|
launcher -H 33554432 -K jbhook3.dll jubeat.dll
|
||||||
3
dist/jb/jbhook-01.conf
vendored
3
dist/jb/jbhook-01.conf
vendored
@@ -1,6 +1,9 @@
|
|||||||
# Run the game windowed
|
# Run the game windowed
|
||||||
gfx.windowed=false
|
gfx.windowed=false
|
||||||
|
|
||||||
|
# rotate the normally-horizontal game window to be vertical
|
||||||
|
gfx.vertical=false
|
||||||
|
|
||||||
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
|
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
|
||||||
eamuse.server=localhost:80
|
eamuse.server=localhost:80
|
||||||
|
|
||||||
|
|||||||
18
dist/jb/jbhook-02.conf
vendored
Normal file
18
dist/jb/jbhook-02.conf
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Run the game windowed
|
||||||
|
gfx.windowed=false
|
||||||
|
|
||||||
|
# rotate the normally-horizontal game window to be vertical
|
||||||
|
gfx.vertical=false
|
||||||
|
|
||||||
|
# URL (e.g. http://my.eamuse.server:80/whatever) or IPV4 (e.g. 127.0.0.1:80) of the target eamuse server. The port is optional but defaults to 80.
|
||||||
|
eamuse.server=localhost:80
|
||||||
|
|
||||||
|
# PCBID
|
||||||
|
eamuse.pcbid=0101020304050607086F
|
||||||
|
|
||||||
|
# EAMID
|
||||||
|
eamuse.eamid=0101020304050607086F
|
||||||
|
|
||||||
|
# Mcode of the game to run.
|
||||||
|
security.mcode=GCI44JAA
|
||||||
|
|
||||||
5
dist/jb/jbio-h44b.conf
vendored
Normal file
5
dist/jb/jbio-h44b.conf
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# H44B serial port
|
||||||
|
h44b.port=COM2
|
||||||
|
|
||||||
|
# H44B bus baudrate (real devices expect 57600)
|
||||||
|
h44b.baud=57600
|
||||||
8
dist/sdvx5/sdvxhook2.conf
vendored
8
dist/sdvx5/sdvxhook2.conf
vendored
@@ -19,7 +19,7 @@ gfx.framed=true
|
|||||||
# Run the game windowed
|
# Run the game windowed
|
||||||
gfx.windowed=false
|
gfx.windowed=false
|
||||||
|
|
||||||
# Confine mouse coursor to window
|
# Confine mouse cursor to window
|
||||||
gfx.confined=false
|
gfx.confined=false
|
||||||
|
|
||||||
# Windowed width, -1 for default size
|
# Windowed width, -1 for default size
|
||||||
@@ -28,6 +28,12 @@ gfx.window_width=1080
|
|||||||
# Windowed height, -1 for default size
|
# Windowed height, -1 for default size
|
||||||
gfx.window_height=1920
|
gfx.window_height=1920
|
||||||
|
|
||||||
|
# Windowed X, -1 for default X position
|
||||||
|
gfx.window_x=-1
|
||||||
|
|
||||||
|
# Windowed Y, -1 for default Y position
|
||||||
|
gfx.window_y=-1
|
||||||
|
|
||||||
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
|
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
|
||||||
gfx.forced_refresh_rate=-1
|
gfx.forced_refresh_rate=-1
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
# Bemanitools 5 documentation
|
# Bemanitools 5 documentation
|
||||||
|
|
||||||
This folder contains various types of documentation.
|
This folder contains various types of documentation.
|
||||||
|
|
||||||
Table of contents:
|
Table of contents:
|
||||||
|
|
||||||
* Key tools
|
* Key tools
|
||||||
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
|
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
|
||||||
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
|
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
|
||||||
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
||||||
* Game hooks
|
* Game hooks
|
||||||
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
|
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
|
||||||
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
|
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
|
||||||
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
|
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
|
||||||
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
|
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
|
||||||
* Development
|
* Development
|
||||||
* [API](api.md): Available APIs for BT5 and instructions how to use them
|
* [API](api.md): Available APIs for BT5 and instructions how to use them
|
||||||
* [Architecture](architecture.md): Outline of BT5's architecture, how things are designed and why
|
* [Architecture](architecture.md): Outline of BT5's architecture, how things are designed and why
|
||||||
* [Development](development.md): Development environment, building, releasing, etc.
|
* [Development](development.md): Development environment, building, releasing, etc.
|
||||||
* [Developer documentation](dev/README.md): Various lose documentation/notes by developers
|
* [Developer documentation](dev/README.md): Various lose documentation/notes by developers
|
||||||
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
||||||
* Hardware
|
|
||||||
* [Hardware](hardware/README.md): Anything related to hardware, e.g. IO boards
|
## Further external documentation
|
||||||
|
|
||||||
|
A list of external documentation that can be useful when dealing with bemanitools,
|
||||||
|
supported data and hardware.
|
||||||
|
|
||||||
|
* [arcade-docs](https://github.com/Shizmob/arcade-docs): An open (to read and contribute) repository
|
||||||
|
of arcade hardware and software documentation
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
# BIO2 sub IO turntable bypass cable
|
|
||||||
If you upgraded a C02/IO2 wired cabinet, the turntables are connected to the
|
|
||||||
sub IO via a serial line that goes to another sub IO behind the front panel
|
|
||||||
next to the 16seg display. This introduces additional latency as the input
|
|
||||||
data needs to pass through multiple systems/PCBs until it reaches the game.
|
|
||||||
|
|
||||||
This can be reduced by using a so-called "bypass" cable, that connects the
|
|
||||||
turntables directly to the BIO2 sub IO board reducing latency significantly.
|
|
||||||
|
|
||||||
This cable could be ordered with any IIDX upgrade kit including the BIO sub IO
|
|
||||||
board but can also be easily created from scratch.
|
|
||||||
|
|
||||||
## Parts
|
|
||||||
* Some wires
|
|
||||||
* [JST HL](https://jst.de/file/download/219/pitch-3-96-mm-wtw-hl2-pdf) 2x4 pin female connector
|
|
||||||
* [JST HVQ](https://jst.de/file/download/637/hvq) 8 pin female connector
|
|
||||||
* Matching terminals for the connectors
|
|
||||||
|
|
||||||
## Pinout
|
|
||||||
```text
|
|
||||||
JST HL 2x4 pin front view connector
|
|
||||||
|
|
||||||
notch at top
|
|
||||||
___
|
|
||||||
|---------|
|
|
||||||
| 1 2 3 4 |
|
|
||||||
| 5 6 7 8 |
|
|
||||||
|---------|
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
JST HVQ 8 pin front view connector
|
|
||||||
Numbering on connector matches
|
|
||||||
|
|
||||||
notch at top
|
|
||||||
___________________
|
|
||||||
-------------------
|
|
||||||
|-----------------|
|
|
||||||
| 1 2 3 4 5 6 7 8 |
|
|
||||||
|-----------------|
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Pins of the two connectors need to be connected like this:
|
|
||||||
| JST HL 2x4 pin | JST 8 pin |
|
|
||||||
|----------------|-----------|
|
|
||||||
| 1 | 1 |
|
|
||||||
| 2 | 1 |
|
|
||||||
| 3 | 3 |
|
|
||||||
| 4 | 2 |
|
|
||||||
| 5 | 5 |
|
|
||||||
| 6 | 4 |
|
|
||||||
| 7 | 8 |
|
|
||||||
| 8 | 8 |
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
# Ezusb 1/2 RJ45 to DIN8 connector pinout
|
|
||||||
This was created from using the BIO2 sub IO board to connect pre IIDX 25 cabinet hardware to the
|
|
||||||
BIO2 IO board. The two connector types from different generation IO boards, RJ45 on the ezusb FX
|
|
||||||
(C02) board and a round DIN8 connector on the ezusb FX2 (IO2) board are just different connectors to
|
|
||||||
the same hardware on the PCB.
|
|
||||||
|
|
||||||
Therefore, any C02 wired cabinet can be easily upgraded to IO2 wiring and vice versa by building
|
|
||||||
a simple RJ45 -> DIN8 or DIN8 -> RJ45 adapter.
|
|
||||||
|
|
||||||
The following connection information was traced on a original Konami BIO2 sub IO board.
|
|
||||||
|
|
||||||
RJ45 (female) connector, top view:
|
|
||||||
```text
|
|
||||||
plug insert
|
|
||||||
|
|
|
||||||
|
|
|
||||||
v
|
|
||||||
|-----------|
|
|
||||||
| Top view |
|
|
||||||
| |
|
|
||||||
| Pins |
|
|
||||||
| 7 5 3 1 |
|
|
||||||
| 8 6 4 2 |
|
|
||||||
|-----------|
|
|
||||||
```
|
|
||||||
|
|
||||||
DIN8 (female) connector, top view:
|
|
||||||
```text
|
|
||||||
plug insert
|
|
||||||
|
|
|
||||||
|
|
|
||||||
v
|
|
||||||
|-----------|
|
|
||||||
| Top view |
|
|
||||||
| Pins |
|
|
||||||
| 3 1 2 6 |
|
|
||||||
| 7 4 5 8 9 |
|
|
||||||
|-----------|
|
|
||||||
```
|
|
||||||
|
|
||||||
The two connectors are interconnected on the PCB like this:
|
|
||||||
| RJ45 pins | DIN8 pins |
|
|
||||||
|-----------|-----------|
|
|
||||||
| 1 | 1 |
|
|
||||||
| 2 | 7 |
|
|
||||||
| 3 | 4 |
|
|
||||||
| 4 | 6 |
|
|
||||||
| 5 | 5 |
|
|
||||||
| 6 | 3 |
|
|
||||||
| 7 | 2 |
|
|
||||||
| 8 | 1 |
|
|
||||||
@@ -23,14 +23,14 @@ games:
|
|||||||
* [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage
|
* [iidxhook8](iidxhook8.md): CANNON BALLERS, Rootage
|
||||||
* [iidxhook8](iidxhook9.md): Heroic Verse
|
* [iidxhook8](iidxhook9.md): Heroic Verse
|
||||||
|
|
||||||
When building kactools, independent packages are created for each set of games
|
When building bemanitools, independent packages are created for each set of games
|
||||||
which are ready to be dropped on top of vanilla AC data dumps. We recommend
|
which are ready to be dropped on top of vanilla AC data dumps. We recommend
|
||||||
using prestine dumps to avoid any conflicts with other hardcoded hacks or
|
using pristine dumps to avoid any conflicts with other hardcoded hacks or
|
||||||
binary patches.
|
binary patches.
|
||||||
|
|
||||||
## How to run
|
## How to run
|
||||||
To run your game with iidxhook, you have to use the inject tool to inject the
|
To run your game with iidxhook, you have to use the inject tool to inject the
|
||||||
DLL to the game process. *dist/iidx* contains bat scripts with all the
|
DLL to the game process. `dist/iidx` contains bat scripts with all the
|
||||||
important parameters configured. Further parameters can be added but might not
|
important parameters configured. Further parameters can be added but might not
|
||||||
be required to run the game with default settings.
|
be required to run the game with default settings.
|
||||||
Further information on how to setup the data for each specific version are
|
Further information on how to setup the data for each specific version are
|
||||||
@@ -47,4 +47,4 @@ IO hardware you want to use:
|
|||||||
game controllers
|
game controllers
|
||||||
* [iidxio-bio2](iidxhook/iidxio-bio2.md): Support BIO2 hardware
|
* [iidxio-bio2](iidxhook/iidxio-bio2.md): Support BIO2 hardware
|
||||||
* [iidxio-ezusb](iidxhook/iidxio-ezusb.md): Support C02 ezusb FX hardware
|
* [iidxio-ezusb](iidxhook/iidxio-ezusb.md): Support C02 ezusb FX hardware
|
||||||
* [iidxio-ezusb2](iidxhook/iidxio-ezusb2.md): Support IO2 ezusb FX2 hardware
|
* [iidxio-ezusb2](iidxhook/iidxio-ezusb2.md): Support IO2 ezusb FX2 hardware
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ If you want to run the games online, you have to set a valid PCBID and EAMID
|
|||||||
argument. You also have to set the url of the eamuse server you want to
|
argument. You also have to set the url of the eamuse server you want to
|
||||||
connect to.
|
connect to.
|
||||||
|
|
||||||
|
Additional note regarding EAMID: This is new compared to the prior games and
|
||||||
|
is provided as the identifier of the "eamuse license" to the server. Depending
|
||||||
|
on the implementation of the server, this can lead to authentication failure
|
||||||
|
resulting in
|
||||||
|
[a network error on boot or warning during gameplay](#network-warning-instead-of-network-ok).
|
||||||
|
|
||||||
Run the game with the gamestart-XX.bat file and enable network on the operator
|
Run the game with the gamestart-XX.bat file and enable network on the operator
|
||||||
menu. When enabled, the game seems to hang and expects you to power
|
menu. When enabled, the game seems to hang and expects you to power
|
||||||
cycle the machine (i.e. quit the game and restart it).
|
cycle the machine (i.e. quit the game and restart it).
|
||||||
@@ -134,7 +140,7 @@ value to cut down start-up times.
|
|||||||
|
|
||||||
## "NETWORK WARNING" instead of "NETWORK OK"
|
## "NETWORK WARNING" instead of "NETWORK OK"
|
||||||
This can be caused by:
|
This can be caused by:
|
||||||
* Invalid PCBID
|
* Invalid PCBID/EAMID: Ensure both are [set to the same ID](#eamuse-network-setup)
|
||||||
* Firewall blocking connections
|
* Firewall blocking connections
|
||||||
* Invalid eamuse url or port specified
|
* Invalid eamuse url or port specified
|
||||||
* Game is not run using the Administrator account
|
* Game is not run using the Administrator account
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
The following games are compatible with this version of iidxhook:
|
The following games are compatible with this version of iidxhook:
|
||||||
* Heroic Verse
|
* Heroic Verse
|
||||||
|
* BISTROVER
|
||||||
|
|
||||||
The games must be bootstrapped using [launcher](../launcher.md).
|
The games must be bootstrapped using [launcher](../launcher.md).
|
||||||
|
|
||||||
|
|||||||
77
doc/jbhook/README.md
Normal file
77
doc/jbhook/README.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# jbhook
|
||||||
|
|
||||||
|
jbhook is a collection of hook libraries for jubeat 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 jbhook version
|
||||||
|
(see below).
|
||||||
|
|
||||||
|
# Versions
|
||||||
|
|
||||||
|
jbhook comes in a few different flavors. The game and its engine changed over
|
||||||
|
the years. Some game versions might require patches/parameters enabled which
|
||||||
|
others don't need or have different AVS versions. Here is the list of supported
|
||||||
|
games:
|
||||||
|
* [jbhook1](jbhook1.md): jubeat, ripples
|
||||||
|
* [jbhook2](jbhook2.md): knit, copious
|
||||||
|
* [jbhook3](jbhook3.md): saucer, prop, qubell, clan, festo
|
||||||
|
|
||||||
|
I sure have trouble remembering which jubeat version is which, here's a handy
|
||||||
|
guide:
|
||||||
|
* 01 - jubeat
|
||||||
|
* 02 - ripples
|
||||||
|
* 03 - knit
|
||||||
|
* 04 - copious
|
||||||
|
* 05 - saucer
|
||||||
|
* 06 - prop
|
||||||
|
* 07 - qubell
|
||||||
|
* 08 - clan
|
||||||
|
* 09 - festo
|
||||||
|
|
||||||
|
When building bemanitools, independent packages are created for each set of games
|
||||||
|
which are ready to be dropped on top of vanilla AC data dumps. We recommend
|
||||||
|
using pristine dumps to avoid any conflicts with other hardcoded hacks or
|
||||||
|
binary patches.
|
||||||
|
|
||||||
|
# How to run
|
||||||
|
|
||||||
|
To run your game with jbhook, you have to use the inject tool to inject the
|
||||||
|
DLL to the game process. `dist/jb` contains bat scripts with all the
|
||||||
|
important parameters configured. Further parameters can be added but might not
|
||||||
|
be required to run the game with default settings.
|
||||||
|
Further information on how to setup the data for each specific version are
|
||||||
|
elaborated in their dedicated readme files.
|
||||||
|
|
||||||
|
# Data setup and running the game
|
||||||
|
|
||||||
|
Ensure your folder with your unpacked data looks like this:
|
||||||
|
- `data`
|
||||||
|
- `prop`
|
||||||
|
- Various dll files including `jubeat.dll` **OR** `jubeat.exe`
|
||||||
|
|
||||||
|
Unpack the package containing jbhook into the folder containing the jubeat
|
||||||
|
binary file.
|
||||||
|
|
||||||
|
Run the `gamestart-XX.bat` file where `XX` denotes the version of the game you want to run.
|
||||||
|
|
||||||
|
# Eamuse network setup
|
||||||
|
|
||||||
|
Running jubeat or ripples? Modify jbhook-01.conf or jbhook-02.conf.
|
||||||
|
|
||||||
|
Running anything newer?
|
||||||
|
* Open the `prop/ea3-config.xml`
|
||||||
|
* Replace the `ea3/network/services` URL with network service URL of your
|
||||||
|
choice (for example http://my.eamuse.com)
|
||||||
|
* Edit the `ea3/id/pcbid`
|
||||||
|
|
||||||
|
# Real hardware support
|
||||||
|
|
||||||
|
Run the launcher without the hook dll: `launcher jubeat.dll`
|
||||||
|
|
||||||
|
# Command line options
|
||||||
|
|
||||||
|
Add the argument *-h* when running inject with jbhook to print help/usage
|
||||||
|
information with a list of parameters you can apply to tweak various things.
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Game list
|
|
||||||
|
|
||||||
The following games are compatible with this version of jbhook:
|
|
||||||
* saucer
|
|
||||||
* prop
|
|
||||||
* qubell
|
|
||||||
|
|
||||||
# Data setup and running the game
|
|
||||||
|
|
||||||
Ensure your folder with your unpacked data looks like this:
|
|
||||||
- data
|
|
||||||
- prop
|
|
||||||
- Various dll files including jubeat.dll
|
|
||||||
|
|
||||||
Unpack the package containing jbhook into the folder containing the jubeat.dll
|
|
||||||
file.
|
|
||||||
|
|
||||||
Run the gamestart.bat file.
|
|
||||||
|
|
||||||
# Eamuse network setup
|
|
||||||
|
|
||||||
* Open the prop/ea3-config.xml
|
|
||||||
* Replace the *ea3/network/services* URL with network service URL of your
|
|
||||||
choice (for example http://my.eamuse.com)
|
|
||||||
* Edit the *ea3/id/pcbid*
|
|
||||||
|
|
||||||
# Real hardware support
|
|
||||||
|
|
||||||
Run the launcher without the hook dll: *launcher jubeat.dll*
|
|
||||||
|
|
||||||
# Troubleshooting and FAQ
|
|
||||||
42
doc/jbhook/jbhook1.md
Normal file
42
doc/jbhook/jbhook1.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Game list
|
||||||
|
|
||||||
|
The following games are compatible with this version of jbhook:
|
||||||
|
* jubeat
|
||||||
|
* jubeat ripples
|
||||||
|
|
||||||
|
The games must be bootstrapped using [inject](../inject.md).
|
||||||
|
|
||||||
|
# Data setup and running the game
|
||||||
|
|
||||||
|
Unpack the package containing jbhook1 into the revision folder of your choice.
|
||||||
|
Most likely, you want to target the latest revision you have to run the latest
|
||||||
|
binary of the game with any bugfixes by developers.
|
||||||
|
|
||||||
|
The DLLs in this package should be in the same location as the game DLLs and
|
||||||
|
executable - i.e. all these files should be in the same folder:
|
||||||
|
- `inject.exe`
|
||||||
|
- `jubeat.exe`
|
||||||
|
- `jbhook-01.conf`
|
||||||
|
- `eamio.dll`
|
||||||
|
- `libavs-win32.dll`
|
||||||
|
- etc
|
||||||
|
|
||||||
|
Run the `gamestart-01.bat` file as admin.
|
||||||
|
|
||||||
|
# Eamuse network setup
|
||||||
|
|
||||||
|
If you want to run the games online, you have to set a valid PCBID in the
|
||||||
|
configuration file. You also have to set the url of the eamuse server you want
|
||||||
|
to connect to.
|
||||||
|
|
||||||
|
# Eamuse network setup
|
||||||
|
|
||||||
|
If you want to run the games online, you have to set a valid PCBID and EAMID
|
||||||
|
(use the PCBID as the EAMID) in the configuration file or as a command line
|
||||||
|
argument. You also have to set the url of the eamuse server you want to
|
||||||
|
connect to.
|
||||||
|
|
||||||
|
Additional note regarding EAMID: This is provided as the identifier of the
|
||||||
|
"eamuse license" to the server. Depending on the implementation of the server,
|
||||||
|
this can lead to authentication failure resulting in a network error on boot or
|
||||||
|
warning during gameplay.
|
||||||
42
doc/jbhook/jbhook2.md
Normal file
42
doc/jbhook/jbhook2.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Game list
|
||||||
|
|
||||||
|
The following games are compatible with this version of jbhook:
|
||||||
|
* jubeat knit
|
||||||
|
* jubeat copious
|
||||||
|
|
||||||
|
The games must be bootstrapped using [launcher](../launcher.md).
|
||||||
|
|
||||||
|
# Data setup and running the game
|
||||||
|
|
||||||
|
Unpack the package containing jbhook2 into the revision folder of your choice.
|
||||||
|
Most likely, you want to target the latest revision you have to run the latest
|
||||||
|
binary of the game with any bugfixes by developers.
|
||||||
|
|
||||||
|
The DLLs in this package should be in the same location as the game DLLs and
|
||||||
|
executable - i.e. all these files should be in the same folder:
|
||||||
|
- `launcher.exe`
|
||||||
|
- `jubeat.dll`
|
||||||
|
- `eamio.dll`
|
||||||
|
- `jbhook2.dll`
|
||||||
|
- `libavs-win32.dll`
|
||||||
|
- etc
|
||||||
|
|
||||||
|
Run the `gamestart-02.bat` file as admin.
|
||||||
|
|
||||||
|
# Eamuse network setup
|
||||||
|
|
||||||
|
If you want to run the games online, you have to set a valid PCBID in the
|
||||||
|
configuration file. You also have to set the url of the eamuse server you want
|
||||||
|
to connect to.
|
||||||
|
|
||||||
|
# Eamuse network setup
|
||||||
|
|
||||||
|
If you want to run the games online, you have to set a valid PCBID and EAMID
|
||||||
|
(use the PCBID as the EAMID) in the configuration file or as a command line
|
||||||
|
argument. You also have to set the url of the eamuse server you want to
|
||||||
|
connect to.
|
||||||
|
|
||||||
|
Additional note regarding EAMID: This is provided as the identifier of the
|
||||||
|
"eamuse license" to the server. Depending on the implementation of the server,
|
||||||
|
this can lead to authentication failure resulting in a network error on boot or
|
||||||
|
warning during gameplay.
|
||||||
18
doc/jbhook/jbhook3.md
Normal file
18
doc/jbhook/jbhook3.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Game list
|
||||||
|
|
||||||
|
The following games are compatible with this version of jbhook:
|
||||||
|
* jubeat saucer
|
||||||
|
* jubeat prop
|
||||||
|
* jubeat qubell
|
||||||
|
* jubeat clan
|
||||||
|
* jubeat festo
|
||||||
|
|
||||||
|
The games must be bootstrapped using [launcher](../launcher.md).
|
||||||
|
|
||||||
|
# Data setup and running the game
|
||||||
|
|
||||||
|
Unpack the package containing jbhook3 into the revision folder of your choice.
|
||||||
|
Most likely, you want to target the latest revision you have to run the latest
|
||||||
|
binary of the game with any bugfixes by developers.
|
||||||
|
|
||||||
|
Run the `gamestart-03.bat` file as admin.
|
||||||
18
doc/jbhook/jbio-p4io.md
Normal file
18
doc/jbhook/jbio-p4io.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
This library talks to a P4IO (panel) and H44B through ACIO (lights) of a jubeat cab and implements the jbio API of BT5.
|
||||||
|
Thus, it allows you to use a modern jubeat cab with *any* version of jubeat that is supported by BT5.
|
||||||
|
|
||||||
|
# Setup
|
||||||
|
* Rename `jbio-p4io.dll` to `jbio.dll`.
|
||||||
|
* Make sure `jbio.dll` is in the same folder as both `jbhook.dll`, `aciomgr.dll` and `jubeat.dll`
|
||||||
|
* If you want IC card support via eamio-icca, ensure you also rename `eamio-icca.dll` to `eamio.dll`
|
||||||
|
* Ensure that your `gamestart.bat` actually injects the appropriate jbhook dll
|
||||||
|
for example:
|
||||||
|
```
|
||||||
|
launcher -K jbhook.dll jubeat.dll ...*
|
||||||
|
```
|
||||||
|
or that the application otherwise uses `jbio.dll`
|
||||||
|
|
||||||
|
* If you have P4IO but no H44B, lights will be disabled
|
||||||
|
* You can change the port and baudrate of the H44B node by editing the `jbio-h44b.conf` that should be created by default
|
||||||
|
* If you are using IC card support, you can edit `eamio-icc.conf` to change the port and baudrate
|
||||||
|
* If you are playing on a real cab, the port and baud of H44B and ICCA should be identical
|
||||||
@@ -58,5 +58,5 @@ Turntables are either in absolute or relative mode depending on how it's defined
|
|||||||
* Make sure that you follow the instructions exactly from the release page
|
* Make sure that you follow the instructions exactly from the release page
|
||||||
([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
|
([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
|
||||||
* If you get an error while trying to install KB3033929, re-enable windows update
|
* If you get an error while trying to install KB3033929, re-enable windows update
|
||||||
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be
|
* If you can't find some of these files, see bemanitools-supplements
|
||||||
done once)
|
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ Thus, it allows you to use a real cab with *any* game that supports xinput.
|
|||||||
* VOL LR are mapped to L thumbstick X/Y (either in absolute or relative mode depending on the config)
|
* VOL LR are mapped to L thumbstick X/Y (either in absolute or relative mode depending on the config)
|
||||||
|
|
||||||
# Additional Notes For Cabinets (Running on embedded Windows 7):
|
# Additional Notes For Cabinets (Running on embedded Windows 7):
|
||||||
* Make sure that you follow the instructions exactly from the release page ([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
|
* Make sure that you follow the instructions exactly from the release page
|
||||||
|
([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
|
||||||
* If you get an error while trying to install KB3033929, re-enable windows update
|
* If you get an error while trying to install KB3033929, re-enable windows update
|
||||||
|
* If you can't find some of these files, see bemanitools-supplements
|
||||||
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)
|
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)
|
||||||
|
|||||||
28
scripts/ci/create-release-message.sh
Executable file
28
scripts/ci/create-release-message.sh
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
VERSION="$1"
|
||||||
|
|
||||||
|
section_active=""
|
||||||
|
changelog_excerpt=""
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [ "$section_active" ]; then
|
||||||
|
if [[ "$(echo "$line" | grep '^#')" ]]; then
|
||||||
|
section_active=""
|
||||||
|
else
|
||||||
|
changelog_excerpt="$(printf "%s\n%s" "$changelog_excerpt" "$line")"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$line" = "## $VERSION" ]; then
|
||||||
|
section_active="1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$changelog_excerpt" ]; then
|
||||||
|
printf "%s" "$changelog_excerpt"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
>&2 echo "Could not find version in changelog: $VERSION"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -46,6 +46,12 @@ struct property_node;
|
|||||||
struct avs_net_interface {
|
struct avs_net_interface {
|
||||||
uint8_t mac_addr[6];
|
uint8_t mac_addr[6];
|
||||||
uint8_t unknown[30];
|
uint8_t unknown[30];
|
||||||
|
#if AVS_VERSION >= 1603
|
||||||
|
uint8_t unknown2[6];
|
||||||
|
#endif
|
||||||
|
#if AVS_VERSION >= 1700
|
||||||
|
uint8_t unknown3[6];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum psmap_type {
|
enum psmap_type {
|
||||||
|
|||||||
10
src/imports/glhelper.h
Normal file
10
src/imports/glhelper.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
void glFramebufferTexture2DEXT(GLenum target,
|
||||||
|
GLenum attachment,
|
||||||
|
GLenum textarget,
|
||||||
|
GLuint texture,
|
||||||
|
GLint level);
|
||||||
|
|
||||||
|
void glGenFramebuffersEXT(GLsizei n,
|
||||||
|
GLuint *ids);
|
||||||
5
src/imports/import_32_1002_avs-ea3.def
Normal file
5
src/imports/import_32_1002_avs-ea3.def
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
LIBRARY libavs-win32-ea3
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
ea3_boot
|
||||||
|
ea3_shutdown
|
||||||
37
src/imports/import_32_1002_avs.def
Normal file
37
src/imports/import_32_1002_avs.def
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
LIBRARY libavs-win32
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
avs_boot
|
||||||
|
avs_net_ctrl
|
||||||
|
avs_shutdown
|
||||||
|
avs_thread_create
|
||||||
|
avs_thread_destroy
|
||||||
|
avs_thread_exit
|
||||||
|
avs_thread_join
|
||||||
|
log_body_fatal
|
||||||
|
log_body_info
|
||||||
|
log_body_misc
|
||||||
|
log_body_warning
|
||||||
|
log_boot
|
||||||
|
log_change_level
|
||||||
|
property_create
|
||||||
|
property_desc_to_buffer
|
||||||
|
property_destroy
|
||||||
|
property_file_write
|
||||||
|
property_insert_read
|
||||||
|
property_mem_write
|
||||||
|
property_read_query_memsize
|
||||||
|
property_search
|
||||||
|
property_set_flag
|
||||||
|
property_node_clone
|
||||||
|
property_node_create
|
||||||
|
property_node_datasize
|
||||||
|
property_node_name
|
||||||
|
property_node_refer
|
||||||
|
property_node_remove
|
||||||
|
property_node_type
|
||||||
|
property_node_traversal
|
||||||
|
property_node_refdata
|
||||||
|
std_getenv
|
||||||
|
std_setenv
|
||||||
|
|
||||||
6
src/imports/import_32_1002_glhelper.def
Normal file
6
src/imports/import_32_1002_glhelper.def
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
LIBRARY glhelper
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
glBindFramebufferEXT
|
||||||
|
glFramebufferTexture2DEXT
|
||||||
|
glGenFramebuffersEXT
|
||||||
6
src/imports/import_32_1101_glhelper.def
Normal file
6
src/imports/import_32_1101_glhelper.def
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
LIBRARY glhelper
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
glBindFramebufferEXT
|
||||||
|
glFramebufferTexture2DEXT
|
||||||
|
glGenFramebuffersEXT
|
||||||
6
src/imports/import_32_1304_glhelper.def
Normal file
6
src/imports/import_32_1304_glhelper.def
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
LIBRARY glhelper
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
glBindFramebufferEXT
|
||||||
|
glFramebufferTexture2DEXT
|
||||||
|
glGenFramebuffersEXT
|
||||||
6
src/imports/import_32_803_glhelper.def
Normal file
6
src/imports/import_32_803_glhelper.def
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
LIBRARY glhelper
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
glBindFramebufferEXT
|
||||||
|
glFramebufferTexture2DEXT
|
||||||
|
glGenFramebuffersEXT
|
||||||
7
src/imports/import_64_1509_avs-ea3.def
Normal file
7
src/imports/import_64_1509_avs-ea3.def
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
LIBRARY libavs-win64-ea3
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
ea3_boot @8 NONAME
|
||||||
|
ea3_get_boot_status @11 NONAME
|
||||||
|
ea3_get_pp_status @10 NONAME
|
||||||
|
ea3_shutdown @9 NONAME
|
||||||
32
src/imports/import_64_1509_avs.def
Normal file
32
src/imports/import_64_1509_avs.def
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
LIBRARY libavs-win64
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
avs_boot @285 NONAME
|
||||||
|
avs_fs_close @65 NONAME
|
||||||
|
avs_fs_lseek @59 NONAME
|
||||||
|
avs_fs_lseek64 @60 NONAME
|
||||||
|
avs_fs_open @58 NONAME
|
||||||
|
avs_fs_read @61 NONAME
|
||||||
|
avs_net_ctrl @98 NONAME
|
||||||
|
avs_shutdown @286 NONAME
|
||||||
|
avs_thread_create @6 NONAME
|
||||||
|
avs_thread_destroy @8 NONAME
|
||||||
|
avs_thread_exit @12 NONAME
|
||||||
|
avs_thread_join @13 NONAME
|
||||||
|
log_body_fatal @357 NONAME
|
||||||
|
log_body_info @359 NONAME
|
||||||
|
log_body_misc @360 NONAME
|
||||||
|
log_body_warning @358 NONAME
|
||||||
|
property_create @127 NONAME
|
||||||
|
property_desc_to_buffer @129 NONAME
|
||||||
|
property_destroy @128 NONAME
|
||||||
|
property_insert_read @131 NONAME
|
||||||
|
property_node_create @145 NONAME
|
||||||
|
property_node_refer @158 NONAME
|
||||||
|
property_node_remove @146 NONAME
|
||||||
|
property_psmap_export @162 NONAME
|
||||||
|
property_psmap_import @161 NONAME
|
||||||
|
property_read_query_memsize @159 NONAME
|
||||||
|
property_search @144 NONAME
|
||||||
|
std_getenv @207 NONAME
|
||||||
|
std_setenv @208 NONAME
|
||||||
@@ -5,9 +5,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "acio/h44b.h"
|
||||||
#include "acio/hdxs.h"
|
#include "acio/hdxs.h"
|
||||||
#include "acio/icca.h"
|
#include "acio/icca.h"
|
||||||
#include "acio/kfca.h"
|
#include "acio/kfca.h"
|
||||||
|
#include "acio/mdxf.h"
|
||||||
|
#include "acio/panb.h"
|
||||||
|
#include "acio/rvol.h"
|
||||||
|
|
||||||
#define AC_IO_SOF 0xAA
|
#define AC_IO_SOF 0xAA
|
||||||
#define AC_IO_ESCAPE 0xFF
|
#define AC_IO_ESCAPE 0xFF
|
||||||
@@ -35,8 +39,11 @@ enum ac_io_node_type {
|
|||||||
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
|
AC_IO_NODE_TYPE_LED_STRIP = 0x04020000,
|
||||||
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
|
AC_IO_NODE_TYPE_LED_SPIKE = 0x05010000,
|
||||||
AC_IO_NODE_TYPE_KFCA = 0x09060000,
|
AC_IO_NODE_TYPE_KFCA = 0x09060000,
|
||||||
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
|
|
||||||
AC_IO_NODE_TYPE_RVOL = 0x09060001,
|
AC_IO_NODE_TYPE_RVOL = 0x09060001,
|
||||||
|
AC_IO_NODE_TYPE_MDXF = 0x09070000,
|
||||||
|
AC_IO_NODE_TYPE_PANB = 0x090E0000,
|
||||||
|
AC_IO_NODE_TYPE_BMPU = 0x0B000000,
|
||||||
|
AC_IO_NODE_TYPE_BI2A = 0x0D060000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@@ -69,13 +76,24 @@ struct ac_io_message {
|
|||||||
uint8_t param;
|
uint8_t param;
|
||||||
struct ac_io_version version;
|
struct ac_io_version version;
|
||||||
|
|
||||||
|
struct ac_io_h44b_output h44b_output;
|
||||||
|
|
||||||
struct ac_io_icca_misc icca_misc;
|
struct ac_io_icca_misc icca_misc;
|
||||||
struct ac_io_icca_state icca_state;
|
struct ac_io_icca_state icca_state;
|
||||||
|
|
||||||
struct ac_io_kfca_poll_in kfca_poll_in;
|
struct ac_io_kfca_poll_in kfca_poll_in;
|
||||||
struct ac_io_kfca_poll_out kfca_poll_out;
|
struct ac_io_kfca_poll_out kfca_poll_out;
|
||||||
|
|
||||||
|
struct ac_io_panb_poll_in panb_poll_in;
|
||||||
|
struct ac_io_panb_poll_out panb_poll_out;
|
||||||
|
|
||||||
struct ac_io_hdxs_output hdxs_output;
|
struct ac_io_hdxs_output hdxs_output;
|
||||||
|
|
||||||
|
struct ac_io_rvol_poll_in rvol_poll_in;
|
||||||
|
struct ac_io_rvol_poll_out rvol_poll_out;
|
||||||
|
|
||||||
|
struct ac_io_mdxf_poll_in mdxf_poll_in;
|
||||||
|
struct ac_io_mdxf_light_out mdxf_light_out;
|
||||||
};
|
};
|
||||||
} cmd;
|
} cmd;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ struct ac_io_h44b_output {
|
|||||||
uint8_t right_rgb[3];
|
uint8_t right_rgb[3];
|
||||||
uint8_t title_rgb[3];
|
uint8_t title_rgb[3];
|
||||||
uint8_t woofer_rgb[3];
|
uint8_t woofer_rgb[3];
|
||||||
};
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,13 +4,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum ac_io_icca_cmd {
|
enum ac_io_icca_cmd {
|
||||||
|
/* found on jubeat, sent right after queue loop start */
|
||||||
|
AC_IO_ICCA_CMD_UNKN_0116 = 0x0116,
|
||||||
/* Yet unknown command encountered first on jubeat (1) */
|
/* 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_QUEUE_LOOP_START = 0x0130,
|
||||||
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
|
AC_IO_ICCA_CMD_ENGAGE = 0x0131,
|
||||||
AC_IO_ICCA_CMD_POLL = 0x0134,
|
AC_IO_ICCA_CMD_POLL = 0x0134,
|
||||||
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
|
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
|
||||||
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
|
AC_IO_ICCA_CMD_DEVICE_CONTROL = 0x013A,
|
||||||
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
|
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
|
||||||
AC_IO_ICCA_CMD_KEY_EXCHANGE = 0x0160,
|
AC_IO_ICCA_CMD_KEY_EXCHANGE = 0x0160,
|
||||||
AC_IO_ICCA_CMD_POLL_ENCRYPTED = 0x0164,
|
AC_IO_ICCA_CMD_POLL_ENCRYPTED = 0x0164,
|
||||||
@@ -29,6 +31,14 @@ enum ac_io_icca_sensor_state {
|
|||||||
AC_IO_ICCA_SENSOR_MASK_BACK_ON = (1 << 5)
|
AC_IO_ICCA_SENSOR_MASK_BACK_ON = (1 << 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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_IDLE_NEW = 0x04,
|
||||||
|
AC_IO_ICCA_STATUS_BUSY_NEW = 0x01,
|
||||||
|
};
|
||||||
|
|
||||||
enum ac_io_icca_keypad_mask {
|
enum ac_io_icca_keypad_mask {
|
||||||
AC_IO_ICCA_KEYPAD_MASK_EMPTY = (1 << 0),
|
AC_IO_ICCA_KEYPAD_MASK_EMPTY = (1 << 0),
|
||||||
AC_IO_ICCA_KEYPAD_MASK_3 = (1 << 1),
|
AC_IO_ICCA_KEYPAD_MASK_3 = (1 << 1),
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#ifndef AC_IO_ICCB_H
|
|
||||||
#define AC_IO_ICCB_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum ac_io_iccb_cmd {
|
|
||||||
/* found on jubeat prop, sent after acio init req, maybe fw update? */
|
|
||||||
AC_IO_ICCB_CMD_UNK_0100 = 0x0100,
|
|
||||||
/* found on jubeat prop, sent right after queue loop start */
|
|
||||||
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_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
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ac_io_iccb_sensor_state {
|
|
||||||
AC_IO_ICCB_SENSOR_CARD = 0x02,
|
|
||||||
AC_IO_ICCB_SENSOR_NO_CARD = 0x04
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ac_io_iccb_card_type {
|
|
||||||
AC_IO_ICCB_CARD_TYPE_ISO15696 = 0x0,
|
|
||||||
AC_IO_ICCB_CARD_TYPE_FELICA = 0x1,
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
|
|
||||||
struct ac_io_iccb_misc {
|
|
||||||
uint8_t unknown;
|
|
||||||
uint8_t subcmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ac_io_iccb_state {
|
|
||||||
uint8_t sensor_state;
|
|
||||||
uint8_t card_type;
|
|
||||||
uint8_t uid[8];
|
|
||||||
uint8_t unk2;
|
|
||||||
uint8_t unk3;
|
|
||||||
uint8_t unk4[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
49
src/main/acio/mdxf.h
Normal file
49
src/main/acio/mdxf.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef AC_IO_MDXF_H
|
||||||
|
#define AC_IO_MDXF_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define AC_IO_CMD_MDXF_POLL 0x0110
|
||||||
|
#define AC_IO_CMD_MDXF_AUTO_GET_START 0x0116
|
||||||
|
#define AC_IO_CMD_MDXF_LIGHT 0x0113
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
union mdxf_panel_sensors_individual {
|
||||||
|
struct {
|
||||||
|
uint8_t right : 1;
|
||||||
|
uint8_t left : 1;
|
||||||
|
uint8_t down : 1;
|
||||||
|
uint8_t up : 1;
|
||||||
|
uint8_t unused : 4;
|
||||||
|
};
|
||||||
|
uint8_t raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mdxf_panel_sensors {
|
||||||
|
uint8_t down : 4;
|
||||||
|
uint8_t up : 4;
|
||||||
|
uint8_t right : 4;
|
||||||
|
uint8_t left : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_mdxf_poll_in {
|
||||||
|
struct mdxf_panel_sensors panel;
|
||||||
|
uint8_t unk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mdxf_lights {
|
||||||
|
uint8_t up_right;
|
||||||
|
uint8_t down_left;
|
||||||
|
uint8_t up_left;
|
||||||
|
uint8_t down_right;
|
||||||
|
uint8_t unk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_mdxf_light_out {
|
||||||
|
struct mdxf_lights side[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif
|
||||||
42
src/main/acio/panb.h
Normal file
42
src/main/acio/panb.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#ifndef AC_IO_PANB_H
|
||||||
|
#define AC_IO_PANB_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define AC_IO_CMD_PANB_POLL_REPLY 0x0110
|
||||||
|
#define AC_IO_CMD_PANB_SEND_LAMP 0x0111
|
||||||
|
#define AC_IO_CMD_PANB_START_AUTO_INPUT 0x0115
|
||||||
|
|
||||||
|
#define AC_IO_PANB_NUM_NODES 4
|
||||||
|
#define AC_IO_PANB_MAX_KEYS (7*AC_IO_PANB_NUM_NODES)
|
||||||
|
#define AC_IO_PANB_MAX_KEYPAIRS (AC_IO_PANB_MAX_KEYS/2)
|
||||||
|
|
||||||
|
struct ac_io_panb_keypair {
|
||||||
|
uint8_t key2 : 4;
|
||||||
|
uint8_t key1 : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct ac_io_panb_poll_in {
|
||||||
|
/* last received command sequence number (start_auto_input / send_lamp) */
|
||||||
|
uint8_t sub_seq1;
|
||||||
|
/* auto-increment sequence number for autopoll reports */
|
||||||
|
uint8_t sub_seq2;
|
||||||
|
struct ac_io_panb_keypair keypair[AC_IO_PANB_MAX_KEYPAIRS];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct ac_io_panb_color {
|
||||||
|
uint8_t red;
|
||||||
|
uint8_t green;
|
||||||
|
uint8_t blue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct ac_io_panb_poll_out {
|
||||||
|
struct ac_io_panb_color key[AC_IO_PANB_MAX_KEYS];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
74
src/main/acio/rvol.h
Normal file
74
src/main/acio/rvol.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#ifndef AC_IO_RVOL_H
|
||||||
|
#define AC_IO_RVOL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// technically RVOL also can poll with CMD 0x0113
|
||||||
|
// but museca never uses this (it's controlled by if the watchdog is on/off)
|
||||||
|
#define AC_IO_CMD_RVOL_POLL 0x0112
|
||||||
|
#define AC_IO_CMD_RVOL_SET_EXPAND_MODE 0x0114
|
||||||
|
#define AC_IO_CMD_RVOL_AMP_CONTROL 0x0128
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
struct ac_io_rvol_buttons_1 {
|
||||||
|
uint8_t unk0 : 1;
|
||||||
|
uint8_t unk1 : 1;
|
||||||
|
uint8_t spinner_4 : 1;
|
||||||
|
uint8_t pedal : 1;
|
||||||
|
uint8_t spinner_5 : 1;
|
||||||
|
uint8_t unk5 : 1;
|
||||||
|
uint8_t unk6 : 1;
|
||||||
|
uint8_t unk7 : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_rvol_buttons_2 {
|
||||||
|
uint8_t spinner_2 : 1;
|
||||||
|
uint8_t unk1 : 1;
|
||||||
|
uint8_t unk2 : 1;
|
||||||
|
uint8_t spinner_1 : 1;
|
||||||
|
uint8_t unk4 : 1;
|
||||||
|
uint8_t unk5 : 1;
|
||||||
|
uint8_t unk6 : 1;
|
||||||
|
uint8_t unk7 : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_rvol_buttons_3 {
|
||||||
|
uint8_t unk0 : 1;
|
||||||
|
uint8_t unk1 : 1;
|
||||||
|
uint8_t unk2 : 1;
|
||||||
|
uint8_t spinner_3 : 1;
|
||||||
|
uint8_t unk4 : 1;
|
||||||
|
uint8_t unk5 : 1;
|
||||||
|
uint8_t unk6 : 1;
|
||||||
|
uint8_t unk7 : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_rvol_poll_in {
|
||||||
|
uint8_t unk_0;
|
||||||
|
struct ac_io_rvol_buttons_1 buttons_1;
|
||||||
|
uint8_t unk_2_8[7];
|
||||||
|
struct ac_io_rvol_buttons_2 buttons_2;
|
||||||
|
uint8_t unk_10;
|
||||||
|
struct ac_io_rvol_buttons_3 buttons_3;
|
||||||
|
uint8_t unk_12_15[4];
|
||||||
|
uint8_t spinners[5];
|
||||||
|
uint8_t unk_21_22[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct light_rgb {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ac_io_rvol_poll_out {
|
||||||
|
uint8_t unk0_3[4];
|
||||||
|
struct light_rgb spinner[5];
|
||||||
|
struct light_rgb title;
|
||||||
|
uint8_t unk22_31[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif
|
||||||
7
src/main/aciodrv-proc/Module.mk
Normal file
7
src/main/aciodrv-proc/Module.mk
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
libs += aciodrv-proc
|
||||||
|
|
||||||
|
libs_aciodrv-proc := \
|
||||||
|
|
||||||
|
src_aciodrv-proc := \
|
||||||
|
panb.c \
|
||||||
|
|
||||||
90
src/main/aciodrv-proc/panb.c
Normal file
90
src/main/aciodrv-proc/panb.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#define LOG_MODULE "aciodrv-proc-panb"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
#include "aciodrv/panb.h"
|
||||||
|
|
||||||
|
#include "util/thread.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
static int auto_poll_proc(void *auto_poll_param);
|
||||||
|
static int auto_poll_threadid;
|
||||||
|
|
||||||
|
static CRITICAL_SECTION keypair_lock;
|
||||||
|
static struct ac_io_panb_keypair _keypair[AC_IO_PANB_MAX_KEYPAIRS];
|
||||||
|
|
||||||
|
static CRITICAL_SECTION auto_poll_stop_lock;
|
||||||
|
static bool auto_poll_stop;
|
||||||
|
|
||||||
|
static int auto_poll_proc(void * param)
|
||||||
|
{
|
||||||
|
struct aciodrv_device_ctx * device = (struct aciodrv_device_ctx *) param;
|
||||||
|
struct ac_io_panb_poll_in poll_in;
|
||||||
|
bool stop;
|
||||||
|
|
||||||
|
do {
|
||||||
|
aciodrv_panb_recv_poll(device, &poll_in);
|
||||||
|
|
||||||
|
EnterCriticalSection(&keypair_lock);
|
||||||
|
memcpy(_keypair, poll_in.keypair, AC_IO_PANB_MAX_KEYPAIRS);
|
||||||
|
LeaveCriticalSection(&keypair_lock);
|
||||||
|
|
||||||
|
EnterCriticalSection(&auto_poll_stop_lock);
|
||||||
|
stop = auto_poll_stop;
|
||||||
|
LeaveCriticalSection(&auto_poll_stop_lock);
|
||||||
|
} while (!stop);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device)
|
||||||
|
{
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!aciodrv_panb_start_auto_input(device, 0, AC_IO_PANB_NUM_NODES)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_poll_stop = false;
|
||||||
|
InitializeCriticalSection(&keypair_lock);
|
||||||
|
InitializeCriticalSection(&auto_poll_stop_lock);
|
||||||
|
auto_poll_threadid = thread_create(auto_poll_proc, (void *)device, 0x4000, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_proc_panb_get_state(uint8_t *button_state)
|
||||||
|
{
|
||||||
|
struct ac_io_panb_keypair keypair[AC_IO_PANB_MAX_KEYPAIRS];
|
||||||
|
|
||||||
|
EnterCriticalSection(&keypair_lock);
|
||||||
|
memcpy(keypair, _keypair, AC_IO_PANB_MAX_KEYPAIRS);
|
||||||
|
LeaveCriticalSection(&keypair_lock);
|
||||||
|
|
||||||
|
/* splice the keypairs into separate button values */
|
||||||
|
for (int i=0; i<AC_IO_PANB_MAX_KEYPAIRS; i++) {
|
||||||
|
uint8_t but1 = keypair[i].key1;
|
||||||
|
uint8_t but2 = keypair[i].key2;
|
||||||
|
button_state[2*i] = but1;
|
||||||
|
button_state[2*i+1] = but2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&auto_poll_stop_lock);
|
||||||
|
auto_poll_stop = true;
|
||||||
|
LeaveCriticalSection(&auto_poll_stop_lock);
|
||||||
|
|
||||||
|
thread_join(auto_poll_threadid, NULL);
|
||||||
|
thread_destroy(auto_poll_threadid);
|
||||||
|
|
||||||
|
DeleteCriticalSection(&keypair_lock);
|
||||||
|
DeleteCriticalSection(&auto_poll_stop_lock);
|
||||||
|
|
||||||
|
/* reset is the only way to disable the auto polling on device side */
|
||||||
|
aciodrv_device_reset(device);
|
||||||
|
}
|
||||||
32
src/main/aciodrv-proc/panb.h
Normal file
32
src/main/aciodrv-proc/panb.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef ACIODRV_PROC_PANB_H
|
||||||
|
#define ACIODRV_PROC_PANB_H
|
||||||
|
|
||||||
|
#include "aciodrv/panb.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a PANB device. This will take care of setting up the auto-poll and processing
|
||||||
|
* the poll messages in a separate thread (this is necessary as failing to process messages
|
||||||
|
* fast enough will cause the device to malfunction).
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @return True if successful, false on error.
|
||||||
|
* @note This function spawns a thread. Caller must call aciodrv_proc_panb_fini to properly
|
||||||
|
* terminate.
|
||||||
|
*/
|
||||||
|
bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve latest known button state from the PANB device.
|
||||||
|
*
|
||||||
|
* @param button_state 28 cell array to store button state
|
||||||
|
* (mandatory, upon calling the array contains values between 0 to 15 indicating the keys velocity).
|
||||||
|
* @return True on success, false on error.
|
||||||
|
*/
|
||||||
|
bool aciodrv_proc_panb_get_state(uint8_t *button_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properly terminate the thread and reset the device (this is the only way to stop the auto polling).
|
||||||
|
*/
|
||||||
|
void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
libs += aciodrv
|
libs += aciodrv
|
||||||
|
|
||||||
libs_aciodrv := \
|
libs_aciodrv := \
|
||||||
|
|
||||||
src_aciodrv := \
|
src_aciodrv := \
|
||||||
device.c \
|
device.c \
|
||||||
|
h44b.c \
|
||||||
icca.c \
|
icca.c \
|
||||||
kfca.c \
|
kfca.c \
|
||||||
|
panb.c \
|
||||||
|
rvol.c \
|
||||||
port.c \
|
port.c \
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#define LOG_MODULE "aciodrv-device"
|
#define LOG_MODULE "aciodrv-device"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "aciodrv/device.h"
|
#include "aciodrv/device.h"
|
||||||
@@ -8,34 +9,64 @@
|
|||||||
|
|
||||||
#include "util/hex.h"
|
#include "util/hex.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
#include "util/mem.h"
|
||||||
|
|
||||||
/* Enable to dump all data to the logger */
|
/* Enable to dump all data to the logger */
|
||||||
//#define AC_IO_MSG_LOG
|
//#define AC_IO_MSG_LOG
|
||||||
|
|
||||||
static uint8_t aciodrv_device_msg_counter = 1;
|
#define ACIO_MAX_NODES_PER_PORT 16
|
||||||
static uint8_t aciodrv_device_node_count;
|
|
||||||
static char aviodrv_device_node_products[16][4];
|
|
||||||
|
|
||||||
static bool aciodrv_device_init(void)
|
struct aciodrv_device_ctx {
|
||||||
|
HANDLE fd;
|
||||||
|
struct aciodrv_device_node_version node_versions[ACIO_MAX_NODES_PER_PORT];
|
||||||
|
uint8_t msg_counter;
|
||||||
|
uint8_t node_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool aciodrv_device_reset(struct aciodrv_device_ctx *device)
|
||||||
|
{
|
||||||
|
uint8_t reset_seq[525] = {0};
|
||||||
|
|
||||||
|
/* init/reset the device by sending 525 NULL bytes */
|
||||||
|
log_info("Resetting device");
|
||||||
|
if (aciodrv_port_write(device->fd, reset_seq, sizeof(reset_seq)) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* signal to device for a reset */
|
||||||
|
EscapeCommFunction(device->fd, SETBREAK);
|
||||||
|
Sleep(1450);
|
||||||
|
EscapeCommFunction(device->fd, CLRBREAK);
|
||||||
|
Sleep(1200);
|
||||||
|
|
||||||
|
/* ignore the next 100 reads (of whatever length) */
|
||||||
|
for (size_t i = 0; i < 100; ++i) {
|
||||||
|
aciodrv_port_read(device->fd, reset_seq, sizeof(reset_seq));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool aciodrv_device_sof_flush(struct aciodrv_device_ctx *device)
|
||||||
{
|
{
|
||||||
uint8_t init_seq[1] = {AC_IO_SOF};
|
uint8_t init_seq[1] = {AC_IO_SOF};
|
||||||
uint8_t read_buff[1] = {0x00};
|
uint8_t read_buff[1] = {0};
|
||||||
|
|
||||||
/* init/reset the device by sending 0xAA until 0xAA is returned */
|
/* wait for reset to finish */
|
||||||
int read = 0;
|
int read = 0;
|
||||||
do {
|
do {
|
||||||
if (aciodrv_port_write(init_seq, sizeof(init_seq)) <= 0) {
|
if (aciodrv_port_write(device->fd, init_seq, sizeof(init_seq)) <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
read = aciodrv_port_read(read_buff, sizeof(read_buff));
|
read = aciodrv_port_read(device->fd, read_buff, sizeof(read_buff));
|
||||||
} while ((read <= 0) || (read_buff[0] != init_seq[0]));
|
} while ((read <= 0) || (read_buff[0] != init_seq[0]));
|
||||||
|
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
log_warning("Obtained SOF, clearing out buffer now");
|
log_info("Obtained SOF, clearing out buffer now");
|
||||||
/* empty buffer by reading all data */
|
/* empty buffer by reading all data */
|
||||||
while (read > 0) {
|
while (read > 0) {
|
||||||
read = aciodrv_port_read(init_seq, sizeof(init_seq));
|
read = aciodrv_port_read(device->fd, init_seq, sizeof(init_seq));
|
||||||
}
|
}
|
||||||
log_warning("Cleared buffer, init done");
|
log_warning("Cleared buffer, init done");
|
||||||
|
|
||||||
@@ -46,30 +77,39 @@ static bool aciodrv_device_init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool aciodrv_device_init(struct aciodrv_device_ctx *device)
|
||||||
|
{
|
||||||
|
if (!aciodrv_device_reset(device)) {
|
||||||
|
log_warning("Reset failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return aciodrv_device_sof_flush(device);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
static void
|
static void
|
||||||
aciodrv_device_log_buffer(const char *msg, const uint8_t *buffer, int length)
|
aciodrv_device_log_buffer(struct aciodrv_device_ctx *device, const char *msg, const uint8_t *buffer, int length)
|
||||||
{
|
{
|
||||||
char str[4096];
|
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);
|
log_misc("[%p] %s, length %d: %s", device->fd, msg, length, str);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool aciodrv_device_send(const uint8_t *buffer, int length)
|
static bool aciodrv_device_send(struct aciodrv_device_ctx *device, const uint8_t *buffer, int length)
|
||||||
{
|
{
|
||||||
uint8_t send_buf[512];
|
uint8_t send_buf[512];
|
||||||
int send_buf_pos = 0;
|
int send_buf_pos = 0;
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
|
|
||||||
if (length > sizeof(send_buf)) {
|
if (length > sizeof(send_buf)) {
|
||||||
log_warning("Send buffer overflow");
|
log_warning("[%p] Send buffer overflow", device->fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
aciodrv_device_log_buffer("Send (1)", buffer, length);
|
aciodrv_device_log_buffer(device, "Send (1)", buffer, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
send_buf[send_buf_pos++] = AC_IO_SOF;
|
send_buf[send_buf_pos++] = AC_IO_SOF;
|
||||||
@@ -95,18 +135,18 @@ static bool aciodrv_device_send(const uint8_t *buffer, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
aciodrv_device_log_buffer("Send (2)", send_buf, send_buf_pos);
|
aciodrv_device_log_buffer(device, "Send (2)", send_buf, send_buf_pos);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (aciodrv_port_write(send_buf, send_buf_pos) != send_buf_pos) {
|
if (aciodrv_port_write(device->fd, send_buf, send_buf_pos) != send_buf_pos) {
|
||||||
log_warning("Sending data with length %d failed", send_buf_pos);
|
log_warning("[%p] Sending data with length %d failed", device->fd, send_buf_pos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aciodrv_device_receive(uint8_t *buffer, int size)
|
static int aciodrv_device_receive(struct aciodrv_device_ctx *device, uint8_t *buffer, int max_resp_size)
|
||||||
{
|
{
|
||||||
uint8_t recv_buf[512];
|
uint8_t recv_buf[512];
|
||||||
int recv_size = 0;
|
int recv_size = 0;
|
||||||
@@ -118,16 +158,14 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
of 0xAAs before we get a valid message. */
|
of 0xAAs before we get a valid message. */
|
||||||
recv_buf[0] = AC_IO_SOF;
|
recv_buf[0] = AC_IO_SOF;
|
||||||
do {
|
do {
|
||||||
read = aciodrv_port_read(recv_buf, 1);
|
read = aciodrv_port_read(device->fd, recv_buf, 1);
|
||||||
} while (recv_buf[0] == AC_IO_SOF);
|
} while (recv_buf[0] == AC_IO_SOF);
|
||||||
|
|
||||||
if (read > 0) {
|
|
||||||
size += 1;
|
|
||||||
|
|
||||||
|
if (read > 0) {
|
||||||
/* recv_buf[0] is already the first byte of the message.
|
/* recv_buf[0] is already the first byte of the message.
|
||||||
now read until nothing's left */
|
now read until nothing's left */
|
||||||
recv_size++;
|
recv_size++;
|
||||||
size--;
|
|
||||||
|
|
||||||
/* important: we have to know how much data we expect
|
/* important: we have to know how much data we expect
|
||||||
and have to read until we reach the requested amount.
|
and have to read until we reach the requested amount.
|
||||||
@@ -135,9 +173,10 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
need to handle escaping (which relies on an up to
|
need to handle escaping (which relies on an up to
|
||||||
date recv_buf[recv_size]) we loop until we get a
|
date recv_buf[recv_size]) we loop until we get a
|
||||||
non-zero read. */
|
non-zero read. */
|
||||||
while (size > 0) {
|
size_t expected_size = offsetof(struct ac_io_message, cmd.nbytes) + 1;
|
||||||
|
while (recv_size < expected_size) {
|
||||||
do {
|
do {
|
||||||
read = aciodrv_port_read(recv_buf + recv_size, 1);
|
read = aciodrv_port_read(device->fd, recv_buf + recv_size, 1);
|
||||||
} while (read == 0);
|
} while (read == 0);
|
||||||
|
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
@@ -150,7 +189,8 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
/* next byte is our real data
|
/* next byte is our real data
|
||||||
overwrite escape byte */
|
overwrite escape byte */
|
||||||
do {
|
do {
|
||||||
read = aciodrv_port_read(recv_buf + recv_size, 1);
|
read = aciodrv_port_read(
|
||||||
|
device->fd, recv_buf + recv_size, 1);
|
||||||
} while (read == 0);
|
} while (read == 0);
|
||||||
|
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
@@ -161,15 +201,23 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
recv_size += read;
|
recv_size += read;
|
||||||
size -= read;
|
|
||||||
|
if (recv_size > offsetof(struct ac_io_message, cmd.nbytes)) {
|
||||||
|
// header + data + checksum
|
||||||
|
expected_size = offsetof(struct ac_io_message, cmd.raw) + ((struct ac_io_message*)recv_buf)->cmd.nbytes + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
|
aciodrv_device_log_buffer(device, "Recv (1)", recv_buf, recv_size);
|
||||||
log_warning("Expected %d got %d", recv_buf[4], recv_size - 6);
|
log_warning("Expected %d got %d", max_resp_size - 6, recv_buf[4]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* recv_size - 1: omit checksum for checksum calc */
|
/* recv_size - 1: omit checksum for checksum calc */
|
||||||
|
if ((recv_size - 1) > max_resp_size) {
|
||||||
|
log_warning("[%p] Expected %d got %d", device->fd, max_resp_size - 6, recv_buf[4]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
for (int i = 0; i < recv_size - 1; i++) {
|
for (int i = 0; i < recv_size - 1; i++) {
|
||||||
checksum += recv_buf[i];
|
checksum += recv_buf[i];
|
||||||
buffer[i] = recv_buf[i];
|
buffer[i] = recv_buf[i];
|
||||||
@@ -178,12 +226,13 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
result_size = recv_size - 1;
|
result_size = recv_size - 1;
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
aciodrv_device_log_buffer("Recv (2)", buffer, result_size);
|
aciodrv_device_log_buffer(device, "Recv (2)", buffer, result_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (checksum != recv_buf[recv_size - 1]) {
|
if (checksum != recv_buf[recv_size - 1]) {
|
||||||
log_warning(
|
log_warning(
|
||||||
"Invalid message checksum: %02X != %02X",
|
"[%p] Invalid message checksum: %02X != %02X",
|
||||||
|
device->fd,
|
||||||
checksum,
|
checksum,
|
||||||
recv_buf[recv_size - 1]);
|
recv_buf[recv_size - 1]);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -195,7 +244,7 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t aciodrv_device_enum_nodes(void)
|
static uint8_t aciodrv_device_enum_nodes(struct aciodrv_device_ctx *device)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
@@ -205,7 +254,9 @@ static uint8_t aciodrv_device_enum_nodes(void)
|
|||||||
msg.cmd.count = 0;
|
msg.cmd.count = 0;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Enumerating nodes failed");
|
log_warning("Enumerating nodes failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -215,7 +266,7 @@ static uint8_t aciodrv_device_enum_nodes(void)
|
|||||||
return msg.cmd.count;
|
return msg.cmd.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
|
static bool aciodrv_device_get_version(struct aciodrv_device_ctx *device, uint8_t node_id, struct aciodrv_device_node_version *version)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
@@ -224,6 +275,7 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
|
|||||||
msg.cmd.nbytes = 0;
|
msg.cmd.nbytes = 0;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
|
device,
|
||||||
&msg,
|
&msg,
|
||||||
offsetof(struct ac_io_message, cmd.raw) +
|
offsetof(struct ac_io_message, cmd.raw) +
|
||||||
sizeof(struct ac_io_version))) {
|
sizeof(struct ac_io_version))) {
|
||||||
@@ -247,12 +299,16 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
|
|||||||
msg.cmd.version.date,
|
msg.cmd.version.date,
|
||||||
msg.cmd.version.time);
|
msg.cmd.version.time);
|
||||||
|
|
||||||
memcpy(product, msg.cmd.version.product_code, 4);
|
memcpy(version->product, msg.cmd.version.product_code, ACIO_NODE_PRODUCT_CODE_LEN);
|
||||||
|
version->type = ac_io_u32(msg.cmd.version.type);
|
||||||
|
version->major = msg.cmd.version.major;
|
||||||
|
version->minor = msg.cmd.version.minor;
|
||||||
|
version->revision = msg.cmd.version.revision;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool aciodrv_device_start_node(uint8_t node_id)
|
static bool aciodrv_device_start_node(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
@@ -261,7 +317,9 @@ static bool aciodrv_device_start_node(uint8_t node_id)
|
|||||||
msg.cmd.nbytes = 0;
|
msg.cmd.nbytes = 0;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Starting node %d failed", node_id);
|
log_warning("Starting node %d failed", node_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -270,80 +328,135 @@ static bool aciodrv_device_start_node(uint8_t node_id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_device_open(const char *port, int baud)
|
// deprecated name
|
||||||
|
struct aciodrv_device_ctx *aciodrv_device_open(const char *port_path, int baud)
|
||||||
{
|
{
|
||||||
if (!aciodrv_port_open(port, baud)) {
|
return aciodrv_device_open_path(port_path, baud);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aciodrv_device_ctx *aciodrv_device_open_path(const char *port_path, int baud)
|
||||||
|
{
|
||||||
|
HANDLE port = aciodrv_port_open(port_path, baud);
|
||||||
|
|
||||||
|
if (!port) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aciodrv_device_ctx *device = xmalloc(sizeof(struct aciodrv_device_ctx));
|
||||||
|
|
||||||
|
memset(device, 0, sizeof(struct aciodrv_device_ctx));
|
||||||
|
device->fd = port;
|
||||||
|
device->msg_counter = 1;
|
||||||
|
|
||||||
|
if (!aciodrv_device_init(device)) {
|
||||||
|
aciodrv_device_close(device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->node_count = aciodrv_device_enum_nodes(device);
|
||||||
|
|
||||||
|
if (device->node_count == 0) {
|
||||||
|
aciodrv_device_close(device);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aciodrv_device_init()) {
|
for (uint8_t i = 0; i < device->node_count; i++) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aciodrv_device_node_count = aciodrv_device_enum_nodes();
|
|
||||||
if (aciodrv_device_node_count == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
|
|
||||||
if (!aciodrv_device_get_version(
|
if (!aciodrv_device_get_version(
|
||||||
i + 1, aviodrv_device_node_products[i])) {
|
device, i + 1, &device->node_versions[i])) {
|
||||||
return false;
|
aciodrv_device_close(device);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
|
for (uint8_t i = 0; i < device->node_count; i++) {
|
||||||
if (!aciodrv_device_start_node(i + 1)) {
|
if (!aciodrv_device_start_node(device, i + 1)) {
|
||||||
return false;
|
aciodrv_device_close(device);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
log_info("Opening ACIO device on [%p]", device->fd);
|
||||||
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t aciodrv_device_get_node_count(void)
|
uint8_t aciodrv_device_get_node_count(struct aciodrv_device_ctx *device)
|
||||||
{
|
{
|
||||||
return aciodrv_device_node_count;
|
return device->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4])
|
bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, uint8_t node_id, char product[ACIO_NODE_PRODUCT_CODE_LEN])
|
||||||
{
|
{
|
||||||
if (aciodrv_device_node_count == 0 || node_id > aciodrv_device_node_count) {
|
if (device->node_count == 0 || node_id > device->node_count) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(product, aviodrv_device_node_products[node_id], 4);
|
memcpy(product, device->node_versions[node_id].product, ACIO_NODE_PRODUCT_CODE_LEN);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
uint32_t aciodrv_device_get_node_product_type(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
|
|
||||||
{
|
{
|
||||||
msg->cmd.seq_no = aciodrv_device_msg_counter++;
|
if (device->node_count == 0 || node_id > device->node_count) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return device->node_versions[node_id].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct aciodrv_device_node_version *aciodrv_device_get_node_product_version(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
|
{
|
||||||
|
if (device->node_count == 0 || node_id > device->node_count) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &device->node_versions[node_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_send(struct aciodrv_device_ctx *device, struct ac_io_message *msg)
|
||||||
|
{
|
||||||
|
msg->cmd.seq_no = device->msg_counter++;
|
||||||
int send_size = offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes;
|
int send_size = offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes;
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
#ifdef AC_IO_MSG_LOG
|
||||||
log_info(
|
log_info(
|
||||||
"Beginning send on %d: %04x (%d b)",
|
"[%p] Beginning send on %d: %04x (%d b)",
|
||||||
|
device->fd,
|
||||||
msg->addr,
|
msg->addr,
|
||||||
msg->cmd.code,
|
msg->cmd.code,
|
||||||
send_size);
|
send_size);
|
||||||
#endif
|
#endif
|
||||||
if (aciodrv_device_send((uint8_t *) msg, send_size) <= 0) {
|
if (aciodrv_device_send(device, (uint8_t *) msg, send_size) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size)
|
||||||
|
{
|
||||||
|
#ifdef AC_IO_MSG_LOG
|
||||||
|
log_info("[%p] Beginning recv: (%d b)", device->fd, max_resp_size);
|
||||||
|
#endif
|
||||||
|
if (aciodrv_device_receive(device, (uint8_t *) msg, max_resp_size) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_send_and_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size)
|
||||||
|
{
|
||||||
|
if (!aciodrv_send(device, msg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t req_code = msg->cmd.code;
|
uint16_t req_code = msg->cmd.code;
|
||||||
|
|
||||||
#ifdef AC_IO_MSG_LOG
|
if (!aciodrv_recv(device, msg, max_resp_size)) {
|
||||||
log_info("Beginning recv: (%d b)", resp_size);
|
|
||||||
#endif
|
|
||||||
if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req_code != msg->cmd.code) {
|
if (req_code != msg->cmd.code) {
|
||||||
log_warning(
|
log_warning(
|
||||||
"Received invalid response %04X for request %04X",
|
"[%p] Received invalid response %04X for request %04X",
|
||||||
|
device->fd,
|
||||||
msg->cmd.code,
|
msg->cmd.code,
|
||||||
req_code);
|
req_code);
|
||||||
return false;
|
return false;
|
||||||
@@ -352,7 +465,13 @@ bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aciodrv_device_close(void)
|
void aciodrv_device_close(struct aciodrv_device_ctx *device)
|
||||||
{
|
{
|
||||||
aciodrv_port_close();
|
log_assert(device);
|
||||||
|
|
||||||
|
log_info("Closing ACIO on [%p]", device->fd);
|
||||||
|
|
||||||
|
aciodrv_port_close(device->fd);
|
||||||
|
|
||||||
|
free(device);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,48 +5,119 @@
|
|||||||
|
|
||||||
#include "acio/acio.h"
|
#include "acio/acio.h"
|
||||||
|
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
#define ACIO_NODE_PRODUCT_CODE_LEN 4
|
||||||
|
|
||||||
|
struct aciodrv_device_ctx;
|
||||||
|
|
||||||
|
struct aciodrv_device_node_version {
|
||||||
|
char product[ACIO_NODE_PRODUCT_CODE_LEN];
|
||||||
|
uint32_t type;
|
||||||
|
uint8_t major;
|
||||||
|
uint8_t minor;
|
||||||
|
uint8_t revision;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open an ACIO device connected to a serial port.
|
* Open an ACIO device connected to a serial port.
|
||||||
*
|
*
|
||||||
* @param port Port the device is connected to (e.g. "COM1")
|
* @param port Port the device is connected to (e.g. "COM1")
|
||||||
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
|
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
|
||||||
* @return True if opening the port and resetting the device was successful,
|
* @return opened device context, NULL on error
|
||||||
* false on error.
|
|
||||||
*/
|
*/
|
||||||
bool aciodrv_device_open(const char *port, int baud);
|
struct aciodrv_device_ctx *aciodrv_device_open(const char *port_path, int baud)
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__attribute__((deprecated("Use aciomgr instead if device is shareable, else aciodrv_device_open_path")))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
struct aciodrv_device_ctx *aciodrv_device_open_path(const char *port_path, int baud);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the node count on the opened device.
|
* Get the node count on the opened device.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @return Total num of nodes enumerated on the ACIO device.
|
* @return Total num of nodes enumerated on the ACIO device.
|
||||||
*/
|
*/
|
||||||
uint8_t aciodrv_device_get_node_count(void);
|
uint8_t aciodrv_device_get_node_count(struct aciodrv_device_ctx *device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the product identifier of an enumerated node.
|
* Get the product identifier of an enumerated node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node. Needs to be in range of the total node count.
|
* @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.
|
* @param product Buffer to return the product id to.
|
||||||
* @return True on success, false on error. If True the variable product
|
* @return True on success, false on error. If True the variable product
|
||||||
* contains the identifier of the queried node.
|
* contains the identifier of the queried node.
|
||||||
*/
|
*/
|
||||||
bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4]);
|
bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, uint8_t node_id, char product[ACIO_NODE_PRODUCT_CODE_LEN]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product identifier of an enumerated node.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node. Needs to be in range of the total node count.
|
||||||
|
* @return product type ID on success, or 0 on failure
|
||||||
|
*/
|
||||||
|
uint32_t aciodrv_device_get_node_product_type(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product version of an enumerated node.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node. Needs to be in range of the total node count.
|
||||||
|
* @return Pointer to the version struct
|
||||||
|
*/
|
||||||
|
const struct aciodrv_device_node_version *aciodrv_device_get_node_product_version(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the ACIO bus and receive an answer.
|
* Send a message to the ACIO bus and receive an answer.
|
||||||
* Use this to implement the protocol for each type of device that can be
|
* Use this to implement the protocol for each type of device that can be
|
||||||
* part of the bus.
|
* part of the bus.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param msg Msg to send to the bus. Make sure that the buffer backing
|
* @param msg Msg to send to the bus. Make sure that the buffer backing
|
||||||
* this message is big enough to receive the response as well.
|
* this message is big enough to receive the response as well.
|
||||||
* @param resp_size Size of the expecting response.
|
* @param resp_size Size of the expecting response.
|
||||||
* @return True on success, false on error.
|
* @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 aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the ACIO bus.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param msg Msg to send to the bus.
|
||||||
|
* @return True on success, false on error.
|
||||||
|
* @note Prefer the use of aciodrv_send_and_recv when possible. This is for commands which don't trigger a reply.
|
||||||
|
*/
|
||||||
|
bool aciodrv_send(struct aciodrv_device_ctx *device, struct ac_io_message *msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a message from the ACIO bus.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param msg Msg to send to the bus. Make sure that the buffer
|
||||||
|
* is big enough to receive the response.
|
||||||
|
* @return True on success, false on error.
|
||||||
|
* @note Prefer the use of aciodrv_send_and_recv when possible. This is for unsollicited incoming messages.
|
||||||
|
*/
|
||||||
|
bool aciodrv_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset an opened device.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @return Total num of nodes enumerated on the ACIO device.
|
||||||
|
*/
|
||||||
|
bool aciodrv_device_reset(struct aciodrv_device_ctx *device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the previously opened ACIO device.
|
* Close the previously opened ACIO device.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
*/
|
*/
|
||||||
void aciodrv_device_close(void);
|
void aciodrv_device_close(struct aciodrv_device_ctx *device);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
45
src/main/aciodrv/h44b.c
Normal file
45
src/main/aciodrv/h44b.c
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#define LOG_MODULE "aciodrv-h44b"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "acio/h44b.h"
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
bool aciodrv_h44b_init(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
|
{
|
||||||
|
// unlike input devices like KFCA, H44B has no watchdog or special init code
|
||||||
|
// requirements - shared ACIO node initialisation is enough
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_h44b_lights(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
const struct ac_io_h44b_output *lights)
|
||||||
|
{
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
log_assert(lights);
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_H44B_CMD_SET_OUTPUTS);
|
||||||
|
msg.cmd.nbytes = sizeof(*lights);
|
||||||
|
msg.cmd.h44b_output = *lights;
|
||||||
|
|
||||||
|
if (!aciodrv_send_and_recv(
|
||||||
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
|
log_warning("Polling of node %d failed", node_id + 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
32
src/main/aciodrv/h44b.h
Normal file
32
src/main/aciodrv/h44b.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef ACIODRV_H44B_H
|
||||||
|
#define ACIODRV_H44B_H
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
#include "acio/h44b.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an H44B node.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
|
* @return True if successful, false on error.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_h44b_init(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the H44B LEDs
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to query (0 based).
|
||||||
|
* @param lights Packed lights struct to send
|
||||||
|
* @return True on success, false on error.
|
||||||
|
*/
|
||||||
|
bool aciodrv_h44b_lights(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
const struct ac_io_h44b_output *lights);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,20 +3,27 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "aciodrv/device.h"
|
#include "aciodrv/device.h"
|
||||||
|
#include "aciodrv/icca.h"
|
||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
|
static bool aciodrv_icca_queue_loop_start(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id;
|
msg.addr = node_id;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_QUEUE_LOOP_START);
|
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_QUEUE_LOOP_START);
|
||||||
msg.cmd.nbytes = 1;
|
msg.cmd.nbytes = 1;
|
||||||
msg.cmd.status = 0;
|
msg.cmd.status = 0;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Starting queue loop failed");
|
log_warning("Starting queue loop failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -27,9 +34,11 @@ static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_icca_init(uint8_t node_id)
|
bool aciodrv_icca_init(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
if (!aciodrv_icca_queue_loop_start(node_id + 1)) {
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!aciodrv_icca_queue_loop_start(device, node_id + 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +46,15 @@ bool aciodrv_icca_init(uint8_t node_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_icca_set_state(
|
bool aciodrv_icca_set_state(
|
||||||
uint8_t node_id, int slot_state, struct ac_io_icca_state *state)
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
int slot_state,
|
||||||
|
struct ac_io_icca_state *state)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_SET_SLOT_STATE);
|
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_SET_SLOT_STATE);
|
||||||
msg.cmd.nbytes = 2;
|
msg.cmd.nbytes = 2;
|
||||||
@@ -49,7 +63,9 @@ bool aciodrv_icca_set_state(
|
|||||||
msg.cmd.raw[1] = slot_state;
|
msg.cmd.raw[1] = slot_state;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
|
||||||
log_warning("Setting state of node %d failed", node_id + 1);
|
log_warning("Setting state of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -61,10 +77,15 @@ bool aciodrv_icca_set_state(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
|
bool aciodrv_icca_get_state(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
struct ac_io_icca_state *state)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL);
|
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL);
|
||||||
msg.cmd.nbytes = 1;
|
msg.cmd.nbytes = 1;
|
||||||
@@ -72,7 +93,9 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
|
|||||||
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
||||||
log_warning("Getting state of node %d failed", node_id + 1);
|
log_warning("Getting state of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -84,10 +107,15 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
|
bool aciodrv_icca_read_card(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
struct ac_io_icca_state *state)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_ENGAGE);
|
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_ENGAGE);
|
||||||
msg.cmd.nbytes = 1;
|
msg.cmd.nbytes = 1;
|
||||||
@@ -95,7 +123,9 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
|
|||||||
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
msg.cmd.count = sizeof(struct ac_io_icca_state);
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
||||||
log_warning("Reading card of node %d failed", node_id + 1);
|
log_warning("Reading card of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -105,4 +135,53 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool aciodrv_icca_is_slotted(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
|
{
|
||||||
|
const struct aciodrv_device_node_version *version;
|
||||||
|
version = aciodrv_device_get_node_product_version(device, node_id);
|
||||||
|
|
||||||
|
// current heuristic is to check if version >= 1.5
|
||||||
|
if (version) {
|
||||||
|
if (version->major == 1) {
|
||||||
|
if (version->minor >= 5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_icca_poll_felica(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
|
{
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL_FELICA);
|
||||||
|
msg.cmd.nbytes = 4;
|
||||||
|
/* buffer size of data we expect */
|
||||||
|
msg.cmd.count = 1;
|
||||||
|
|
||||||
|
// additional data, not sure
|
||||||
|
msg.cmd.raw[1] = 0x03;
|
||||||
|
msg.cmd.raw[2] = 0xFF;
|
||||||
|
msg.cmd.raw[3] = 0xFF;
|
||||||
|
|
||||||
|
if (!aciodrv_send_and_recv(
|
||||||
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
|
||||||
|
log_warning("Reading card of node %d failed", node_id + 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,17 +6,19 @@
|
|||||||
/**
|
/**
|
||||||
* Initialize an ICCA node.
|
* Initialize an ICCA node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to initialize (0 based).
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
* @return True if successful, false on error.
|
* @return True if successful, false on error.
|
||||||
* @note This module is supposed to be used in combination with the common
|
* @note This module is supposed to be used in combination with the common
|
||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_icca_init(uint8_t node_id);
|
bool aciodrv_icca_init(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the state of on ICCA node.
|
* Set the state of on ICCA node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to set the state for (0 based).
|
* @param node_id Id of the node to set the state for (0 based).
|
||||||
* @param slot_state State of the slot (refer to corresponding enum).
|
* @param slot_state State of the slot (refer to corresponding enum).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
@@ -27,11 +29,15 @@ bool aciodrv_icca_init(uint8_t node_id);
|
|||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_icca_set_state(
|
bool aciodrv_icca_set_state(
|
||||||
uint8_t node_id, int slot_state, struct ac_io_icca_state *state);
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
int slot_state,
|
||||||
|
struct ac_io_icca_state *state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current state of an ICCA node.
|
* Get the current state of an ICCA node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
* (optional, NULL for none).
|
* (optional, NULL for none).
|
||||||
@@ -40,7 +46,10 @@ bool aciodrv_icca_set_state(
|
|||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
|
bool aciodrv_icca_get_state(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
struct ac_io_icca_state *state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger a card read action on the ICCA reader. Make sure to call this
|
* Trigger a card read action on the ICCA reader. Make sure to call this
|
||||||
@@ -48,6 +57,7 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
|
|||||||
* to get the most recent card data. Make sure to re-get the state after
|
* to get the most recent card data. Make sure to re-get the state after
|
||||||
* a read call. The state returned here might not be up to date for some reason.
|
* a read call. The state returned here might not be up to date for some reason.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
* (optional, NULL for none).
|
* (optional, NULL for none).
|
||||||
@@ -56,6 +66,46 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
|
|||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state);
|
bool aciodrv_icca_read_card(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
struct ac_io_icca_state *state);
|
||||||
|
|
||||||
#endif
|
/**
|
||||||
|
* Uses some heruistics based on the product ident to determine if the detected
|
||||||
|
* device is a slotted (true) or wavepass reader (false).
|
||||||
|
*
|
||||||
|
* This function will also return false if the provided node_id is invalid.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to query (0 based).
|
||||||
|
* @return True on slotted, false on wavepass.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_icca_is_slotted(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls the felica chip on wavepass readers. This will cause the state of the
|
||||||
|
* reader to be AC_IO_ICCA_STATUS_BUSY_NEW for a few polls, before returning
|
||||||
|
* either: AC_IO_ICCA_STATUS_IDLE_NEW or AC_IO_ICCA_STATUS_GOT_UID.
|
||||||
|
*
|
||||||
|
* The user should take care to call this every so often to actually get new
|
||||||
|
* felica UIDs, instead of just old NFC idents. The game seems to do it every
|
||||||
|
* 5 or so polls after the last AC_IO_ICCA_STATUS_BUSY_NEW poll.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to query (0 based).
|
||||||
|
* @return True on success, false on error.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_icca_poll_felica(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -7,37 +7,35 @@
|
|||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
static bool aciodrv_kfca_watchdog_start(uint8_t node_id)
|
static bool aciodrv_kfca_watchdog_start(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
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)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
|
||||||
msg.cmd.nbytes = 2;
|
msg.cmd.nbytes = 2;
|
||||||
msg.cmd.nbytes = 2;
|
|
||||||
|
|
||||||
// uint16_t: 6000
|
// uint16_t: 6000
|
||||||
msg.cmd.raw[0] = 23;
|
msg.cmd.raw[0] = 23;
|
||||||
msg.cmd.raw[1] = 112;
|
msg.cmd.raw[1] = 112;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(&msg, offsetof(struct ac_io_message, cmd.raw) +
|
if (!aciodrv_send_and_recv(
|
||||||
2)) { log_warning("Starting watchdog failed"); return false;
|
device, &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",
|
log_warning("Started watchdog of node %d, sz: %d, status: %d",
|
||||||
node_id, msg.cmd.status);
|
node_id, msg.cmd.nbytes, msg.cmd.status);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_kfca_amp(
|
bool aciodrv_kfca_amp(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
uint8_t primary,
|
uint8_t primary,
|
||||||
uint8_t headphone,
|
uint8_t headphone,
|
||||||
@@ -46,6 +44,8 @@ bool aciodrv_kfca_amp(
|
|||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
|
||||||
msg.cmd.nbytes = 4;
|
msg.cmd.nbytes = 4;
|
||||||
@@ -56,7 +56,9 @@ bool aciodrv_kfca_amp(
|
|||||||
msg.cmd.raw[3] = subwoofer;
|
msg.cmd.raw[3] = subwoofer;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Setting AMP failed");
|
log_warning("Setting AMP failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -66,13 +68,17 @@ bool aciodrv_kfca_amp(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_kfca_init(uint8_t node_id)
|
bool aciodrv_kfca_init(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
{
|
{
|
||||||
if (!aciodrv_kfca_watchdog_start(node_id)) {
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!aciodrv_kfca_watchdog_start(device, node_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aciodrv_kfca_amp(node_id, 0, 0, 0, 0)) {
|
if (!aciodrv_kfca_amp(device, node_id, 0, 0, 0, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +86,15 @@ bool aciodrv_kfca_init(uint8_t node_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool aciodrv_kfca_poll(
|
bool aciodrv_kfca_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct ac_io_kfca_poll_out *pout,
|
const struct ac_io_kfca_poll_out *pout,
|
||||||
struct ac_io_kfca_poll_in *pin)
|
struct ac_io_kfca_poll_in *pin)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
|
||||||
msg.cmd.nbytes = sizeof(*pout);
|
msg.cmd.nbytes = sizeof(*pout);
|
||||||
@@ -93,7 +102,9 @@ bool aciodrv_kfca_poll(
|
|||||||
msg.cmd.kfca_poll_out = *pout;
|
msg.cmd.kfca_poll_out = *pout;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||||
log_warning("Polling of node %d failed", node_id + 1);
|
log_warning("Polling of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,19 @@
|
|||||||
/**
|
/**
|
||||||
* Initialize an KFCA node.
|
* Initialize an KFCA node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to initialize (0 based).
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
* @return True if successful, false on error.
|
* @return True if successful, false on error.
|
||||||
* @note This module is supposed to be used in combination with the common
|
* @note This module is supposed to be used in combination with the common
|
||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_kfca_init(uint8_t node_id);
|
bool aciodrv_kfca_init(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll the KFCA io board
|
* Poll the KFCA io board
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
* (optional, NULL for none).
|
* (optional, NULL for none).
|
||||||
@@ -26,6 +28,7 @@ bool aciodrv_kfca_init(uint8_t node_id);
|
|||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool aciodrv_kfca_poll(
|
bool aciodrv_kfca_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct ac_io_kfca_poll_out *pout,
|
const struct ac_io_kfca_poll_out *pout,
|
||||||
struct ac_io_kfca_poll_in *pin);
|
struct ac_io_kfca_poll_in *pin);
|
||||||
@@ -33,6 +36,7 @@ bool aciodrv_kfca_poll(
|
|||||||
/**
|
/**
|
||||||
* Set the KFCA digital amp level
|
* Set the KFCA digital amp level
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param primary primary volume (96-0)
|
* @param primary primary volume (96-0)
|
||||||
* @param headphone headphone volume (96-0)
|
* @param headphone headphone volume (96-0)
|
||||||
@@ -42,6 +46,7 @@ bool aciodrv_kfca_poll(
|
|||||||
* @note Note 96 (or 100?) is lowest volume level, 0 is highest
|
* @note Note 96 (or 100?) is lowest volume level, 0 is highest
|
||||||
*/
|
*/
|
||||||
bool aciodrv_kfca_amp(
|
bool aciodrv_kfca_amp(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
uint8_t primary,
|
uint8_t primary,
|
||||||
uint8_t headphone,
|
uint8_t headphone,
|
||||||
|
|||||||
80
src/main/aciodrv/panb.c
Normal file
80
src/main/aciodrv/panb.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#define LOG_MODULE "aciodrv-panb"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
#include "aciodrv/panb.h"
|
||||||
|
|
||||||
|
#include "util/thread.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
bool aciodrv_panb_start_auto_input(struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t node_count)
|
||||||
|
{
|
||||||
|
log_assert(device);
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
/* only the first node is handling the commands */
|
||||||
|
if (node_id != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_START_AUTO_INPUT);
|
||||||
|
msg.cmd.nbytes = 1;
|
||||||
|
msg.cmd.count = node_count;
|
||||||
|
|
||||||
|
if (!aciodrv_send(device, &msg)) {
|
||||||
|
log_warning("Starting auto input failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("Started auto input for %d nodes", node_count);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_panb_recv_poll(struct aciodrv_device_ctx *device, struct ac_io_panb_poll_in *poll_in)
|
||||||
|
{
|
||||||
|
log_assert(device);
|
||||||
|
struct ac_io_message msg;
|
||||||
|
struct ac_io_panb_poll_in *poll_res = (struct ac_io_panb_poll_in *) &msg.cmd.raw;
|
||||||
|
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_POLL_REPLY);
|
||||||
|
msg.cmd.nbytes = sizeof(struct ac_io_panb_poll_in);
|
||||||
|
|
||||||
|
if (!aciodrv_recv(device,
|
||||||
|
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.nbytes + 1)) {
|
||||||
|
log_warning("Getting state failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (poll_in != NULL){
|
||||||
|
memcpy(poll_in, poll_res, sizeof(struct ac_io_panb_poll_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_panb_send_lamp(struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id, struct ac_io_panb_poll_out *state)
|
||||||
|
{
|
||||||
|
log_assert(device);
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
/* only the first node is handling the commands */
|
||||||
|
if (node_id != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_SEND_LAMP);
|
||||||
|
msg.cmd.nbytes = 0x54;
|
||||||
|
memcpy(&msg.cmd.raw, state, sizeof(struct ac_io_panb_poll_out));
|
||||||
|
|
||||||
|
if (!aciodrv_send(device, &msg)) {
|
||||||
|
log_warning("Sending lamp state failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
56
src/main/aciodrv/panb.h
Normal file
56
src/main/aciodrv/panb.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef ACIODRV_PANB_H
|
||||||
|
#define ACIODRV_PANB_H
|
||||||
|
|
||||||
|
#include "acio/panb.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the AC_IO_CMD_PANB_START_AUTO_INPUT command on a PANB device.
|
||||||
|
*
|
||||||
|
* @param device Context of opened device.
|
||||||
|
* @param node_id node_id Id of the node to query (0 based).
|
||||||
|
* @param node_count The number of nodes to poll.
|
||||||
|
* @return True if successful, false on error.
|
||||||
|
* @note node_id should be 0, PANB internally manages the other nodes.
|
||||||
|
* @note Upon calling, the device will stop replying to commands and just keep sending
|
||||||
|
* AC_IO_CMD_PANB_POLL_REPLY messages indefinitely. Failure to retrieve them fast enough
|
||||||
|
* will cause the device to malfunction. It is thus advised to make use of the aciodrv-proc
|
||||||
|
* module to spawn a thread that will handle these messages and provide an easy access to the
|
||||||
|
* latest input state.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_panb_start_auto_input(struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t node_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a AC_IO_CMD_PANB_POLL_REPLY message from a PANB device. This assumes that there
|
||||||
|
* is such message incoming (ie. that start_auto_input has been called prior).
|
||||||
|
*
|
||||||
|
* @param device Context of opened device.
|
||||||
|
* @param poll_in Buffer to hold the received message, or NULL.
|
||||||
|
* @return True if successful, false on error.
|
||||||
|
* @note node_id should be 0, PANB internally manages the other nodes.
|
||||||
|
* @note Failure to retrieve the incoming messages fast enough will cause the device to malfunction.
|
||||||
|
* It is thus advised to make use of the aciodrv-proc module to spawn a thread that will handle these
|
||||||
|
* messages and provide an easy access to the latest input state.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_panb_recv_poll(struct aciodrv_device_ctx *device, struct ac_io_panb_poll_in *poll_in);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Light lamps on a PANB device.
|
||||||
|
*
|
||||||
|
* @param node_id Id of the node to query (0 based).
|
||||||
|
* @param state Pointer to a lamp state struct
|
||||||
|
* (mandatory).
|
||||||
|
* @return True on success, false on error.
|
||||||
|
* @note node_id should be 0, PANB internally manages the other nodes.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_panb_send_lamp(struct aciodrv_device_ctx *device, uint8_t node_id, struct ac_io_panb_poll_out *state);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#define LOG_MODULE "aciodrv-port"
|
#define LOG_MODULE "aciodrv-port"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -7,17 +8,15 @@
|
|||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
static HANDLE aciodrv_port_fd;
|
HANDLE aciodrv_port_open(const char *port_path, int baud)
|
||||||
|
|
||||||
bool aciodrv_port_open(const char *port, int baud)
|
|
||||||
{
|
{
|
||||||
COMMTIMEOUTS ct;
|
COMMTIMEOUTS ct;
|
||||||
DCB dcb;
|
DCB dcb;
|
||||||
|
|
||||||
log_info("Opening ACIO on %s at %d baud", port, baud);
|
log_info("Opening ACIO on %s at %d baud", port_path, baud);
|
||||||
|
|
||||||
aciodrv_port_fd = CreateFile(
|
HANDLE port_fd = CreateFile(
|
||||||
port,
|
port_path,
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -25,26 +24,26 @@ bool aciodrv_port_open(const char *port, int baud)
|
|||||||
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
|
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (aciodrv_port_fd == INVALID_HANDLE_VALUE) {
|
if (port_fd == INVALID_HANDLE_VALUE) {
|
||||||
log_warning("Failed to open %s", port);
|
log_warning("Failed to open %s", port_path);
|
||||||
|
|
||||||
goto early_fail;
|
goto early_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetCommMask(aciodrv_port_fd, EV_RXCHAR)) {
|
if (!SetCommMask(port_fd, EV_RXCHAR)) {
|
||||||
log_warning("SetCommMask failed");
|
log_warning("SetCommMask failed");
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupComm(aciodrv_port_fd, 0x1000, 0x1000)) {
|
if (!SetupComm(port_fd, 0x1000, 0x1000)) {
|
||||||
log_warning("SetupComm failed");
|
log_warning("SetupComm failed");
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PurgeComm(
|
if (!PurgeComm(
|
||||||
aciodrv_port_fd,
|
port_fd,
|
||||||
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
|
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
|
||||||
log_warning("PurgeComm failed");
|
log_warning("PurgeComm failed");
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ bool aciodrv_port_open(const char *port, int baud)
|
|||||||
ct.ReadTotalTimeoutMultiplier = 0;
|
ct.ReadTotalTimeoutMultiplier = 0;
|
||||||
ct.WriteTotalTimeoutMultiplier = 0;
|
ct.WriteTotalTimeoutMultiplier = 0;
|
||||||
|
|
||||||
if (!SetCommTimeouts(aciodrv_port_fd, &ct)) {
|
if (!SetCommTimeouts(port_fd, &ct)) {
|
||||||
log_warning("SetCommTimeouts failed");
|
log_warning("SetCommTimeouts failed");
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -65,7 +64,7 @@ bool aciodrv_port_open(const char *port, int baud)
|
|||||||
|
|
||||||
dcb.DCBlength = sizeof(dcb);
|
dcb.DCBlength = sizeof(dcb);
|
||||||
|
|
||||||
if (!GetCommState(aciodrv_port_fd, &dcb)) {
|
if (!GetCommState(port_fd, &dcb)) {
|
||||||
log_warning("GetCommState failed");
|
log_warning("GetCommState failed");
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -90,46 +89,47 @@ bool aciodrv_port_open(const char *port, int baud)
|
|||||||
dcb.XonLim = 100;
|
dcb.XonLim = 100;
|
||||||
dcb.XoffLim = 100;
|
dcb.XoffLim = 100;
|
||||||
|
|
||||||
if (!SetCommState(aciodrv_port_fd, &dcb)) {
|
if (!SetCommState(port_fd, &dcb)) {
|
||||||
log_warning("SetCommState failed");
|
log_warning("SetCommState failed");
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EscapeCommFunction(aciodrv_port_fd, SETDTR)) {
|
if (!EscapeCommFunction(port_fd, SETDTR)) {
|
||||||
log_warning("SETDTR failed: err = %lu", GetLastError());
|
log_warning("SETDTR failed: err = %lu", GetLastError());
|
||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("Opened ACIO device on %s", port);
|
log_info("[%p] Opened ACIO device on %s", port_fd, port_path);
|
||||||
|
|
||||||
return true;
|
return port_fd;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
CloseHandle(aciodrv_port_fd);
|
CloseHandle(port_fd);
|
||||||
|
|
||||||
early_fail:
|
early_fail:
|
||||||
aciodrv_port_fd = NULL;
|
return NULL;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int aciodrv_port_read(void *bytes, int nbytes)
|
int aciodrv_port_read(HANDLE port_fd, void *bytes, int nbytes)
|
||||||
{
|
{
|
||||||
DWORD nread;
|
DWORD nread;
|
||||||
|
|
||||||
if (aciodrv_port_fd == NULL) {
|
log_assert(bytes);
|
||||||
|
|
||||||
|
if (port_fd == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ClearCommError(aciodrv_port_fd, NULL, NULL)) {
|
if (!ClearCommError(port_fd, NULL, NULL)) {
|
||||||
log_warning("ClearCommError failed");
|
log_warning("[%p] ClearCommError failed", port_fd);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadFile(aciodrv_port_fd, bytes, nbytes, &nread, NULL)) {
|
if (!ReadFile(port_fd, bytes, nbytes, &nread, NULL)) {
|
||||||
log_warning("ReadFile failed: err = %lu", GetLastError());
|
log_warning("[%p] ReadFile failed: err = %lu", port_fd, GetLastError());
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -137,16 +137,18 @@ int aciodrv_port_read(void *bytes, int nbytes)
|
|||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aciodrv_port_write(const void *bytes, int nbytes)
|
int aciodrv_port_write(HANDLE port_fd, const void *bytes, int nbytes)
|
||||||
{
|
{
|
||||||
DWORD nwrit;
|
DWORD nwrit;
|
||||||
|
|
||||||
if (aciodrv_port_fd == NULL) {
|
log_assert(bytes);
|
||||||
|
|
||||||
|
if (port_fd == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteFile(aciodrv_port_fd, bytes, nbytes, &nwrit, NULL)) {
|
if (!WriteFile(port_fd, bytes, nbytes, &nwrit, NULL)) {
|
||||||
log_warning("WriteFile failed: err = %lu", GetLastError());
|
log_warning("[%p] WriteFile failed: err = %lu", port_fd, GetLastError());
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -154,9 +156,9 @@ int aciodrv_port_write(const void *bytes, int nbytes)
|
|||||||
return nwrit;
|
return nwrit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aciodrv_port_close(void)
|
void aciodrv_port_close(HANDLE port_fd)
|
||||||
{
|
{
|
||||||
if (aciodrv_port_fd != NULL) {
|
if (port_fd != NULL) {
|
||||||
CloseHandle(aciodrv_port_fd);
|
CloseHandle(port_fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,39 +4,45 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a serial port for communication with a ACIO device.
|
* Open a serial port for communication with a ACIO device.
|
||||||
*
|
*
|
||||||
* @param port Port the device is connected to (e.g. "COM1")
|
* @param port Port the device is connected to (e.g. "COM1")
|
||||||
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
|
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
|
||||||
* @return True if opening the com port was successful, false on error.
|
* @return HANDLE of the port, NULL on error
|
||||||
* @note This will open and setup the com port, only.
|
* @note This will open and setup the com port, only.
|
||||||
*/
|
*/
|
||||||
bool aciodrv_port_open(const char *port, int baud);
|
HANDLE aciodrv_port_open(const char *port_path, int baud);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read data from the opened com port.
|
* Read data from the opened com port.
|
||||||
*
|
*
|
||||||
|
* @param port_fd HANDLE of opened serial port
|
||||||
* @param bytes Pointer to an allocated buffer to read the data into.
|
* @param bytes Pointer to an allocated buffer to read the data into.
|
||||||
* @param nbytes Number of bytes to read. Has to be less or equal the allocated
|
* @param nbytes Number of bytes to read. Has to be less or equal the allocated
|
||||||
* buffer size.
|
* buffer size.
|
||||||
* @return Number of bytes read on success or -1 on error.
|
* @return Number of bytes read on success or -1 on error.
|
||||||
*/
|
*/
|
||||||
int aciodrv_port_read(void *bytes, int nbytes);
|
int aciodrv_port_read(HANDLE port_fd, void *bytes, int nbytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write data to the opened com port.
|
* Write data to the opened com port.
|
||||||
*
|
*
|
||||||
|
* @param port_fd HANDLE of opened serial port
|
||||||
* @param bytes Pointer to an allocated buffer with data to write.
|
* @param bytes Pointer to an allocated buffer with data to write.
|
||||||
* @param nbytes Number of bytes to write. Has to be equal or less the size
|
* @param nbytes Number of bytes to write. Has to be equal or less the size
|
||||||
* of the allocated buffer.
|
* of the allocated buffer.
|
||||||
* @return Number of bytes written on success or -1 on error.
|
* @return Number of bytes written on success or -1 on error.
|
||||||
*/
|
*/
|
||||||
int aciodrv_port_write(const void *bytes, int nbytes);
|
int aciodrv_port_write(HANDLE port_fd, const void *bytes, int nbytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the previously opened com port.
|
* Close the previously opened com port.
|
||||||
|
*
|
||||||
|
* @param port_fd HANDLE of opened serial port
|
||||||
*/
|
*/
|
||||||
void aciodrv_port_close(void);
|
void aciodrv_port_close(HANDLE port_fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
80
src/main/aciodrv/rvol.c
Normal file
80
src/main/aciodrv/rvol.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#define LOG_MODULE "aciodrv-rvol"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
static bool aciodrv_rvol_change_expand_mode(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
uint8_t mode)
|
||||||
|
{
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_RVOL_SET_EXPAND_MODE);
|
||||||
|
msg.cmd.nbytes = 1;
|
||||||
|
|
||||||
|
msg.cmd.raw[0] = (mode | (2 * mode)) << 6;
|
||||||
|
|
||||||
|
if (!aciodrv_send_and_recv(
|
||||||
|
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
|
log_warning("RVOL change expand mode failed %d", node_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("I/O expand mode set %d, mode: %d",
|
||||||
|
node_id, mode);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_rvol_init(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
|
{
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!aciodrv_rvol_change_expand_mode(device, node_id, 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciodrv_rvol_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
const struct ac_io_rvol_poll_out *pout,
|
||||||
|
struct ac_io_rvol_poll_in *pin)
|
||||||
|
{
|
||||||
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
log_assert(pout);
|
||||||
|
|
||||||
|
msg.addr = node_id + 1;
|
||||||
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_RVOL_POLL);
|
||||||
|
msg.cmd.nbytes = sizeof(*pout);
|
||||||
|
/* buffer size of data we expect */
|
||||||
|
msg.cmd.rvol_poll_out = *pout;
|
||||||
|
|
||||||
|
if (!aciodrv_send_and_recv(
|
||||||
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||||
|
log_warning("Polling of node %d failed", node_id + 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pin != NULL) {
|
||||||
|
memcpy(pin, &msg.cmd.rvol_poll_in, sizeof(*pin));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
36
src/main/aciodrv/rvol.h
Normal file
36
src/main/aciodrv/rvol.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef ACIODRV_RVOL_H
|
||||||
|
#define ACIODRV_RVOL_H
|
||||||
|
|
||||||
|
#include "acio/rvol.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a Revolte (KFCA 1.5) IO board
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
|
* @return True if successful, false on error.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_rvol_init(struct aciodrv_device_ctx *device, uint8_t node_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll a Revolte (KFCA 1.5) IO board
|
||||||
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
|
* @param node_id Id of the node to query (0 based).
|
||||||
|
* @param pout Pointer to a state struct to write to device
|
||||||
|
* @param pin Pointer to a state struct to return the current state to
|
||||||
|
* @return True on success, false on error.
|
||||||
|
* @note This module is supposed to be used in combination with the common
|
||||||
|
* device driver foundation.
|
||||||
|
* @see driver.h
|
||||||
|
*/
|
||||||
|
bool aciodrv_rvol_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id,
|
||||||
|
const struct ac_io_rvol_poll_out *pout,
|
||||||
|
struct ac_io_rvol_poll_in *pin);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -6,6 +6,5 @@ src_acioemu := \
|
|||||||
h44b.c \
|
h44b.c \
|
||||||
hdxs.c \
|
hdxs.c \
|
||||||
icca.c \
|
icca.c \
|
||||||
iccb.c \
|
|
||||||
pipe.c \
|
pipe.c \
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ static HRESULT ac_io_emu_write(struct ac_io_emu *emu, struct irp *irp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this supplies a single SOF byte per byte read
|
||||||
ac_io_in_supply(&emu->in, NULL, 0);
|
ac_io_in_supply(&emu->in, NULL, 0);
|
||||||
ac_io_out_consume_message(&emu->out);
|
ac_io_out_consume_message(&emu->out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ void ac_io_emu_h44b_dispatch_request(
|
|||||||
req->cmd.raw[i * 3 + 2]);
|
req->cmd.raw[i * 3 + 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
jb_io_write_outputs();
|
jb_io_write_lights();
|
||||||
|
|
||||||
ac_io_emu_h44b_send_status(h44b, req, 0x00);
|
ac_io_emu_h44b_send_status(h44b, req, 0x00);
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,6 @@ enum ac_io_icca_flag {
|
|||||||
AC_IO_ICCA_FLAG_SOLENOID = 0x40
|
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_IDLE_NEW = 0x04
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ac_io_emu_icca_cmd_send_version(
|
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);
|
||||||
|
|
||||||
@@ -70,6 +63,8 @@ void ac_io_emu_icca_init(
|
|||||||
|
|
||||||
// default to 1.6.0
|
// default to 1.6.0
|
||||||
icca->version = v160;
|
icca->version = v160;
|
||||||
|
// default, most common code
|
||||||
|
ac_io_emu_icca_set_product_code(icca, AC_IO_EMU_PROD_CODE_ICCA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ac_io_emu_icca_set_version(
|
void ac_io_emu_icca_set_version(
|
||||||
@@ -78,6 +73,12 @@ void ac_io_emu_icca_set_version(
|
|||||||
icca->version = version;
|
icca->version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ac_io_emu_icca_set_product_code(
|
||||||
|
struct ac_io_emu_icca *icca, const char product_code[4])
|
||||||
|
{
|
||||||
|
memcpy(icca->product_code, product_code, sizeof(icca->product_code));
|
||||||
|
}
|
||||||
|
|
||||||
void ac_io_emu_icca_dispatch_request(
|
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)
|
||||||
{
|
{
|
||||||
@@ -126,14 +127,15 @@ void ac_io_emu_icca_dispatch_request(
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AC_IO_ICCA_CMD_UNKN_0116:
|
||||||
case AC_IO_ICCA_CMD_UNKN_0120:
|
case AC_IO_ICCA_CMD_UNKN_0120:
|
||||||
log_misc("AC_IO_ICCA_CMD_UNKN_0120(%d)", req->addr);
|
log_misc("AC_IO_ICCA_CMD_UNK_%04X(%d)", cmd_code, req->addr);
|
||||||
ac_io_emu_icca_send_status(icca, req, 0x00);
|
ac_io_emu_icca_send_status(icca, req, 0x00);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AC_IO_ICCA_CMD_BEGIN_KEYPAD:
|
case AC_IO_ICCA_CMD_DEVICE_CONTROL:
|
||||||
log_misc("AC_IO_ICCA_CMD_BEGIN_KEYPAD(%d)", req->addr);
|
log_misc("AC_IO_ICCA_CMD_DEVICE_CONTROL(%d)", req->addr);
|
||||||
ac_io_emu_icca_send_status(icca, req, 0x00);
|
ac_io_emu_icca_send_status(icca, req, 0x00);
|
||||||
icca->keypad_started = true;
|
icca->keypad_started = true;
|
||||||
|
|
||||||
@@ -145,48 +147,52 @@ void ac_io_emu_icca_dispatch_request(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AC_IO_ICCA_CMD_SET_SLOT_STATE: {
|
case AC_IO_ICCA_CMD_SET_SLOT_STATE: {
|
||||||
struct ac_io_icca_misc *misc =
|
if(icca->version == v150) {
|
||||||
(struct ac_io_icca_misc *) &req->cmd.raw;
|
ac_io_emu_icca_send_state(icca, req, 0, false);
|
||||||
uint8_t cmd;
|
} else {
|
||||||
|
struct ac_io_icca_misc *misc =
|
||||||
|
(struct ac_io_icca_misc *) &req->cmd.raw;
|
||||||
|
uint8_t cmd;
|
||||||
|
|
||||||
switch (misc->subcmd) {
|
switch (misc->subcmd) {
|
||||||
case AC_IO_ICCA_SUBCMD_CARD_SLOT_CLOSE:
|
case AC_IO_ICCA_SUBCMD_CARD_SLOT_CLOSE:
|
||||||
cmd = EAM_IO_CARD_SLOT_CMD_CLOSE;
|
cmd = EAM_IO_CARD_SLOT_CMD_CLOSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AC_IO_ICCA_SUBCMD_CARD_SLOT_OPEN:
|
case AC_IO_ICCA_SUBCMD_CARD_SLOT_OPEN:
|
||||||
cmd = EAM_IO_CARD_SLOT_CMD_OPEN;
|
cmd = EAM_IO_CARD_SLOT_CMD_OPEN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AC_IO_ICCA_SUBCMD_CARD_SLOT_EJECT:
|
case AC_IO_ICCA_SUBCMD_CARD_SLOT_EJECT:
|
||||||
cmd = EAM_IO_CARD_SLOT_CMD_EJECT;
|
cmd = EAM_IO_CARD_SLOT_CMD_EJECT;
|
||||||
icca->engaged = false;
|
icca->engaged = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
cmd = EAM_IO_CARD_SLOT_CMD_READ;
|
cmd = EAM_IO_CARD_SLOT_CMD_READ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmd = 0xFF;
|
cmd = 0xFF;
|
||||||
log_warning(
|
log_warning(
|
||||||
"Unhandled slot command %X, node %d",
|
"Unhandled slot command %X, node %d",
|
||||||
misc->subcmd,
|
misc->subcmd,
|
||||||
icca->unit_no);
|
icca->unit_no);
|
||||||
break;
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* response with current slot state */
|
if (cmd != 0xFF) {
|
||||||
ac_io_emu_icca_send_status(icca, req, misc->subcmd);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* response with current slot state */
|
||||||
|
ac_io_emu_icca_send_status(icca, req, misc->subcmd);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -209,12 +215,14 @@ void ac_io_emu_icca_dispatch_request(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AC_IO_ICCA_CMD_POLL_FELICA:
|
case AC_IO_ICCA_CMD_POLL_FELICA:
|
||||||
icca->detected_new_reader = true;
|
if (icca->version == v150) {
|
||||||
|
ac_io_emu_icca_send_state(icca, req, 0, false);
|
||||||
if (icca->version == v170) {
|
} else if (icca->version == v170) {
|
||||||
ac_io_emu_icca_send_empty(icca, req);
|
ac_io_emu_icca_send_empty(icca, req);
|
||||||
|
icca->detected_new_reader = true;
|
||||||
} else {
|
} else {
|
||||||
ac_io_emu_icca_send_status(icca, req, 0x01);
|
ac_io_emu_icca_send_status(icca, req, 0x01);
|
||||||
|
icca->detected_new_reader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -251,8 +259,6 @@ static void ac_io_emu_icca_cmd_send_version(
|
|||||||
resp.cmd.version.major = 0x01;
|
resp.cmd.version.major = 0x01;
|
||||||
|
|
||||||
if (icca->version == v150) {
|
if (icca->version == v150) {
|
||||||
log_warning(
|
|
||||||
"ICCA v1.5.0 emulation requested, please remove this log once implemented");
|
|
||||||
resp.cmd.version.minor = 0x05;
|
resp.cmd.version.minor = 0x05;
|
||||||
} else if (icca->version == v160) {
|
} else if (icca->version == v160) {
|
||||||
resp.cmd.version.minor = 0x06;
|
resp.cmd.version.minor = 0x06;
|
||||||
@@ -269,7 +275,7 @@ static void ac_io_emu_icca_cmd_send_version(
|
|||||||
|
|
||||||
memcpy(
|
memcpy(
|
||||||
resp.cmd.version.product_code,
|
resp.cmd.version.product_code,
|
||||||
"ICCA",
|
icca->product_code,
|
||||||
sizeof(resp.cmd.version.product_code));
|
sizeof(resp.cmd.version.product_code));
|
||||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
||||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ enum ac_io_emu_icca_version {
|
|||||||
v170 = 0x7,
|
v170 = 0x7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ICC product types for ac_io_emu_icca_set_product_code
|
||||||
|
#define AC_IO_EMU_PROD_CODE_ICCA "ICCA"
|
||||||
|
#define AC_IO_EMU_PROD_CODE_ICCB "ICCB"
|
||||||
|
#define AC_IO_EMU_PROD_CODE_ICCC "ICCC"
|
||||||
|
|
||||||
struct ac_io_emu_icca {
|
struct ac_io_emu_icca {
|
||||||
struct ac_io_emu *emu;
|
struct ac_io_emu *emu;
|
||||||
uint8_t unit_no;
|
uint8_t unit_no;
|
||||||
@@ -28,6 +33,7 @@ struct ac_io_emu_icca {
|
|||||||
uint64_t time_counter_last_poll;
|
uint64_t time_counter_last_poll;
|
||||||
|
|
||||||
enum ac_io_emu_icca_version version;
|
enum ac_io_emu_icca_version version;
|
||||||
|
char product_code[4];
|
||||||
bool cipher_started;
|
bool cipher_started;
|
||||||
uint32_t cipher_keys[4];
|
uint32_t cipher_keys[4];
|
||||||
};
|
};
|
||||||
@@ -39,6 +45,12 @@ void ac_io_emu_icca_init(
|
|||||||
void ac_io_emu_icca_set_version(
|
void ac_io_emu_icca_set_version(
|
||||||
struct ac_io_emu_icca *icca, enum ac_io_emu_icca_version version);
|
struct ac_io_emu_icca *icca, enum ac_io_emu_icca_version version);
|
||||||
|
|
||||||
|
// optional, call after init to override default "ICCA" product code.
|
||||||
|
// Some games may refuse to boot or expect a different packet format when using
|
||||||
|
// one of the alternative codes such as ICCB or ICCC
|
||||||
|
void ac_io_emu_icca_set_product_code(
|
||||||
|
struct ac_io_emu_icca *icca, const char product_code[4]);
|
||||||
|
|
||||||
void ac_io_emu_icca_dispatch_request(
|
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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,219 +0,0 @@
|
|||||||
#define LOG_MODULE "acioemu-iccb"
|
|
||||||
|
|
||||||
#include "acioemu/iccb.h"
|
|
||||||
|
|
||||||
#include <windows.h> /* for _BitScanForward */
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "acio/iccb.h"
|
|
||||||
|
|
||||||
#include "acioemu/emu.h"
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
static void ac_io_emu_iccb_send_state(
|
|
||||||
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);
|
|
||||||
|
|
||||||
static void ac_io_emu_iccb_send_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)
|
|
||||||
{
|
|
||||||
memset(iccb, 0, sizeof(*iccb));
|
|
||||||
iccb->emu = emu;
|
|
||||||
iccb->unit_no = unit_no;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ac_io_emu_iccb_dispatch_request(
|
|
||||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
|
||||||
{
|
|
||||||
uint16_t cmd_code;
|
|
||||||
|
|
||||||
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_iccb_cmd_send_version(iccb, req);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_CMD_START_UP:
|
|
||||||
log_misc("AC_IO_CMD_START_UP(%d)", req->addr);
|
|
||||||
ac_io_emu_iccb_send_status(iccb, req, 0x00);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_CMD_KEEPALIVE:
|
|
||||||
ac_io_emu_iccb_send_empty(iccb, req);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_QUEUE_LOOP_START:
|
|
||||||
log_misc("AC_IO_CMD_QUEUE_LOOP_START(%d)", req->addr);
|
|
||||||
ac_io_emu_iccb_send_status(iccb, req, 0x00);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_UNK_0100:
|
|
||||||
case AC_IO_ICCB_CMD_UNK_0116:
|
|
||||||
case AC_IO_ICCB_CMD_UNK_0120:
|
|
||||||
log_misc("AC_IO_ICCB_CMD_UNK_%04X(%d)", cmd_code, req->addr);
|
|
||||||
ac_io_emu_iccb_send_status(iccb, req, 0x00);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_SLEEP:
|
|
||||||
ac_io_emu_iccb_send_status(iccb, req, 0x00);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_UNK_135:
|
|
||||||
/* log_misc("AC_IO_ICCB_CMD_UNK_135"); */
|
|
||||||
ac_io_emu_iccb_send_state(iccb, req);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_POLL:
|
|
||||||
/* log_misc("AC_IO_ICCB_CMD_POLL"); */
|
|
||||||
ac_io_emu_iccb_send_state(iccb, req);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AC_IO_ICCB_CMD_READ_CARD:
|
|
||||||
/* log_misc("AC_IO_ICCB_CMD_READ_CARD"); */
|
|
||||||
ac_io_emu_iccb_send_state(iccb, req);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
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_message resp;
|
|
||||||
|
|
||||||
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
|
|
||||||
resp.cmd.code = req->cmd.code;
|
|
||||||
resp.cmd.seq_no = req->cmd.seq_no;
|
|
||||||
resp.cmd.nbytes = sizeof(resp.cmd.version);
|
|
||||||
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_ICCB);
|
|
||||||
resp.cmd.version.flag = 0x00;
|
|
||||||
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));
|
|
||||||
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
|
|
||||||
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
|
|
||||||
|
|
||||||
ac_io_emu_response_push(iccb->emu, &resp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ac_io_emu_iccb_send_empty(
|
|
||||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
|
||||||
{
|
|
||||||
struct ac_io_message resp;
|
|
||||||
|
|
||||||
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
|
|
||||||
resp.cmd.code = req->cmd.code;
|
|
||||||
resp.cmd.seq_no = req->cmd.seq_no;
|
|
||||||
resp.cmd.nbytes = 0;
|
|
||||||
|
|
||||||
ac_io_emu_response_push(iccb->emu, &resp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_message resp;
|
|
||||||
|
|
||||||
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
|
|
||||||
resp.cmd.code = req->cmd.code;
|
|
||||||
resp.cmd.seq_no = req->cmd.seq_no;
|
|
||||||
resp.cmd.nbytes = sizeof(resp.cmd.status);
|
|
||||||
resp.cmd.status = status;
|
|
||||||
|
|
||||||
ac_io_emu_response_push(iccb->emu, &resp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ac_io_emu_iccb_send_state(
|
|
||||||
struct ac_io_emu_iccb *iccb, const struct ac_io_message *req)
|
|
||||||
{
|
|
||||||
struct ac_io_message resp;
|
|
||||||
struct ac_io_iccb_state *body;
|
|
||||||
bool sensor;
|
|
||||||
|
|
||||||
/* state update */
|
|
||||||
|
|
||||||
sensor = eam_io_get_sensor_state(iccb->unit_no);
|
|
||||||
|
|
||||||
if (sensor != iccb->last_sensor) {
|
|
||||||
if (sensor) {
|
|
||||||
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);
|
|
||||||
} else {
|
|
||||||
iccb->fault = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iccb->last_sensor = sensor;
|
|
||||||
|
|
||||||
if (iccb->fault) {
|
|
||||||
memset(iccb->uid, 0, sizeof(iccb->uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create response */
|
|
||||||
|
|
||||||
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
|
|
||||||
resp.cmd.code = req->cmd.code;
|
|
||||||
resp.cmd.seq_no = req->cmd.seq_no;
|
|
||||||
resp.cmd.nbytes = sizeof(struct ac_io_iccb_state);
|
|
||||||
|
|
||||||
body = (struct ac_io_iccb_state *) &resp.cmd.raw;
|
|
||||||
|
|
||||||
if (sensor) {
|
|
||||||
body->sensor_state = AC_IO_ICCB_SENSOR_CARD;
|
|
||||||
} else {
|
|
||||||
body->sensor_state = AC_IO_ICCB_SENSOR_NO_CARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iccb->fault) {
|
|
||||||
memcpy(body->uid, iccb->uid, sizeof(body->uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
body->card_type = 0x30 | (iccb->card_result - 1);
|
|
||||||
body->unk2 = 0;
|
|
||||||
// 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
|
|
||||||
body->unk3 = 0x03;
|
|
||||||
memset(body->unk4, 0, sizeof(body->unk4));
|
|
||||||
|
|
||||||
ac_io_emu_response_push(iccb->emu, &resp, 0);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef AC_IO_EMU_ICCB_H
|
|
||||||
#define AC_IO_EMU_ICCB_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "acioemu/emu.h"
|
|
||||||
|
|
||||||
struct ac_io_emu_iccb {
|
|
||||||
struct ac_io_emu *emu;
|
|
||||||
uint8_t unit_no;
|
|
||||||
bool fault;
|
|
||||||
bool last_sensor;
|
|
||||||
uint8_t uid[8];
|
|
||||||
uint8_t card_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ac_io_emu_iccb_init(
|
|
||||||
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);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
9
src/main/aciomgr/Module.mk
Normal file
9
src/main/aciomgr/Module.mk
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
dlls += aciomgr
|
||||||
|
|
||||||
|
libs_aciomgr := \
|
||||||
|
aciodrv \
|
||||||
|
util \
|
||||||
|
|
||||||
|
src_aciomgr := \
|
||||||
|
dllmain.c \
|
||||||
|
manager.c \
|
||||||
12
src/main/aciomgr/aciomgr.def
Normal file
12
src/main/aciomgr/aciomgr.def
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
LIBRARY aciomgr
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
aciomgr_set_loggers
|
||||||
|
aciomgr_port_init
|
||||||
|
aciomgr_port_fini
|
||||||
|
aciomgr_get_node_count
|
||||||
|
aciomgr_get_node_product_ident
|
||||||
|
aciomgr_port_submit_packet
|
||||||
|
aciomgr_port_checkout
|
||||||
|
aciomgr_port_checkin
|
||||||
|
DllMain@12 @1 NONAME
|
||||||
16
src/main/aciomgr/dllmain.c
Normal file
16
src/main/aciomgr/dllmain.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "manager-init.h"
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
|
||||||
|
{
|
||||||
|
if (reason == DLL_PROCESS_ATTACH) {
|
||||||
|
_aciomgr_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason == DLL_PROCESS_DETACH) {
|
||||||
|
_aciomgr_fini();
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
8
src/main/aciomgr/manager-init.h
Normal file
8
src/main/aciomgr/manager-init.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef ACIOMGR_MANAGER_INIT_H
|
||||||
|
#define ACIOMGR_MANAGER_INIT_H
|
||||||
|
|
||||||
|
// internal, used by DllMain
|
||||||
|
void _aciomgr_init();
|
||||||
|
void _aciomgr_fini();
|
||||||
|
|
||||||
|
#endif
|
||||||
210
src/main/aciomgr/manager.c
Normal file
210
src/main/aciomgr/manager.c
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
#define LOG_MODULE "aciomgr-manager"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
#include "aciomgr/manager-init.h"
|
||||||
|
|
||||||
|
#include "aciomgr/manager.h"
|
||||||
|
|
||||||
|
#include "acio/acio.h"
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
#include "util/array.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
#define MAX_PORT_PATH_LENGTH 256
|
||||||
|
|
||||||
|
struct aciomgr_port_dispatcher {
|
||||||
|
CRITICAL_SECTION cs;
|
||||||
|
atomic_size_t references;
|
||||||
|
struct aciodrv_device_ctx *device;
|
||||||
|
char path[MAX_PORT_PATH_LENGTH];
|
||||||
|
int baud;
|
||||||
|
bool has_failure;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _aciomgr_setup_port_dispatcher(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud);
|
||||||
|
static void
|
||||||
|
_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher);
|
||||||
|
|
||||||
|
// DLL-globals
|
||||||
|
static atomic_bool running;
|
||||||
|
static CRITICAL_SECTION mgr_cs;
|
||||||
|
static struct array active_ports;
|
||||||
|
|
||||||
|
static void _aciomgr_setup_port_dispatcher(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&dispatcher->cs);
|
||||||
|
|
||||||
|
strcpy(dispatcher->path, path);
|
||||||
|
dispatcher->baud = baud;
|
||||||
|
|
||||||
|
dispatcher->device = aciodrv_device_open_path(path, baud);
|
||||||
|
dispatcher->has_failure = false;
|
||||||
|
|
||||||
|
if (dispatcher->device == NULL) {
|
||||||
|
log_info("Opening ACIO device on %s failed", path);
|
||||||
|
dispatcher->has_failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatcher->references = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
aciodrv_device_close(dispatcher->device);
|
||||||
|
DeleteCriticalSection(&dispatcher->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _aciomgr_init()
|
||||||
|
{
|
||||||
|
if (running) {
|
||||||
|
log_warning("_aciomgr_init called when already running");
|
||||||
|
_aciomgr_fini();
|
||||||
|
}
|
||||||
|
InitializeCriticalSection(&mgr_cs);
|
||||||
|
array_init(&active_ports);
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _aciomgr_fini()
|
||||||
|
{
|
||||||
|
if (!running) {
|
||||||
|
log_warning("_aciomgr_fini called when not running");
|
||||||
|
}
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
DeleteCriticalSection(&mgr_cs);
|
||||||
|
array_fini(&active_ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aciomgr_set_loggers(
|
||||||
|
log_formatter_t misc,
|
||||||
|
log_formatter_t info,
|
||||||
|
log_formatter_t warning,
|
||||||
|
log_formatter_t fatal)
|
||||||
|
{
|
||||||
|
log_to_external(misc, info, warning, fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud)
|
||||||
|
{
|
||||||
|
if (!running) {
|
||||||
|
log_warning("aciomgr_port_init: called when not running");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(path) >= MAX_PORT_PATH_LENGTH) {
|
||||||
|
log_warning("aciomgr_port_init: path too long");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct aciomgr_port_dispatcher *entry;
|
||||||
|
|
||||||
|
EnterCriticalSection(&mgr_cs);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < active_ports.nitems; i++) {
|
||||||
|
entry = array_item(struct aciomgr_port_dispatcher, &active_ports, i);
|
||||||
|
|
||||||
|
if (strcmp(entry->path, path) == 0) {
|
||||||
|
// found
|
||||||
|
if (entry->baud != baud) {
|
||||||
|
log_warning(
|
||||||
|
"Device at %s opened with baud of %d, but requested %d",
|
||||||
|
path,
|
||||||
|
entry->baud,
|
||||||
|
baud);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = array_append(struct aciomgr_port_dispatcher, &active_ports);
|
||||||
|
_aciomgr_setup_port_dispatcher(entry, path, baud);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (!entry->has_failure) {
|
||||||
|
entry->references++;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&mgr_cs);
|
||||||
|
|
||||||
|
if (entry->has_failure) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
if (!running) {
|
||||||
|
log_warning("aciomgr_port_fini: called when not running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&mgr_cs);
|
||||||
|
dispatcher->references--;
|
||||||
|
LeaveCriticalSection(&mgr_cs);
|
||||||
|
|
||||||
|
if (dispatcher->references == 0) {
|
||||||
|
_aciomgr_destroy_port_dispatcher(dispatcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function don't require the lock
|
||||||
|
uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
return aciodrv_device_get_node_count(dispatcher->device);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function don't require the lock
|
||||||
|
bool aciomgr_get_node_product_ident(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher,
|
||||||
|
uint8_t node_id,
|
||||||
|
char product[ACIOMGR_NODE_PRODUCT_CODE_LEN])
|
||||||
|
{
|
||||||
|
return aciodrv_device_get_node_product_ident(
|
||||||
|
dispatcher->device, node_id, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciomgr_port_submit_packet(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher,
|
||||||
|
struct ac_io_message *msg,
|
||||||
|
int max_resp_size)
|
||||||
|
{
|
||||||
|
// CS's although lightweight, may still be a burden, short circuit
|
||||||
|
if (dispatcher->references > 1) {
|
||||||
|
EnterCriticalSection(&dispatcher->cs);
|
||||||
|
bool response =
|
||||||
|
aciodrv_send_and_recv(dispatcher->device, msg, max_resp_size);
|
||||||
|
LeaveCriticalSection(&dispatcher->cs);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aciodrv_send_and_recv(dispatcher->device, msg, max_resp_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aciodrv_device_ctx *
|
||||||
|
aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
if (dispatcher->references > 1) {
|
||||||
|
EnterCriticalSection(&dispatcher->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatcher->device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher)
|
||||||
|
{
|
||||||
|
if (dispatcher->references > 1) {
|
||||||
|
LeaveCriticalSection(&dispatcher->cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/main/aciomgr/manager.h
Normal file
86
src/main/aciomgr/manager.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#ifndef ACIOMGR_MANAGER_H
|
||||||
|
#define ACIOMGR_MANAGER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "bemanitools/glue.h"
|
||||||
|
|
||||||
|
#define ACIOMGR_NODE_PRODUCT_CODE_LEN 4
|
||||||
|
|
||||||
|
struct ac_io_message;
|
||||||
|
struct aciodrv_device_ctx;
|
||||||
|
struct aciomgr_port_dispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 aciomgr_set_loggers(
|
||||||
|
log_formatter_t misc,
|
||||||
|
log_formatter_t info,
|
||||||
|
log_formatter_t warning,
|
||||||
|
log_formatter_t fatal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init and open, or return the existing handle to an acio port
|
||||||
|
*
|
||||||
|
* @param path Port the device is connected to (e.g. "COM1")
|
||||||
|
* @return opened port dispatcher context, NULL on error
|
||||||
|
*/
|
||||||
|
struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud);
|
||||||
|
|
||||||
|
void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the node count on the opened device.
|
||||||
|
*
|
||||||
|
* @param dispatcher dispatcher context from aciomgr_port_init
|
||||||
|
* @return Total num of nodes enumerated on the ACIO device.
|
||||||
|
*/
|
||||||
|
uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the product identifier of an enumerated node.
|
||||||
|
*
|
||||||
|
* @param dispatcher dispatcher context from aciomgr_port_init
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
bool aciomgr_get_node_product_ident(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher,
|
||||||
|
uint8_t node_id,
|
||||||
|
char product[ACIOMGR_NODE_PRODUCT_CODE_LEN]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit and wait for the response of the specified packet
|
||||||
|
*
|
||||||
|
* @param dispatcher dispatcher context from aciomgr_port_init
|
||||||
|
* @param msg pointer to the message buffer to read from / write to
|
||||||
|
* @param max_resp_size pointer to the max size response we expect
|
||||||
|
* @return false on error
|
||||||
|
*/
|
||||||
|
bool aciomgr_port_submit_packet(
|
||||||
|
struct aciomgr_port_dispatcher *dispatcher,
|
||||||
|
struct ac_io_message *msg,
|
||||||
|
int max_resp_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checkout the device handler for this port dispatcher on this thread
|
||||||
|
*
|
||||||
|
* @param dispatcher dispatcher context from aciomgr_port_init
|
||||||
|
* @return the device context
|
||||||
|
*/
|
||||||
|
struct aciodrv_device_ctx *
|
||||||
|
aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checkin the device handler that this thread holds
|
||||||
|
*
|
||||||
|
* @param dispatcher dispatcher context from aciomgr_port_init
|
||||||
|
*/
|
||||||
|
void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,10 +3,13 @@ exes += aciotest
|
|||||||
libs_aciotest := \
|
libs_aciotest := \
|
||||||
bio2drv \
|
bio2drv \
|
||||||
aciodrv \
|
aciodrv \
|
||||||
|
aciodrv-proc \
|
||||||
util \
|
util \
|
||||||
|
|
||||||
src_aciotest := \
|
src_aciotest := \
|
||||||
icca.c \
|
icca.c \
|
||||||
kfca.c \
|
kfca.c \
|
||||||
|
panb.c \
|
||||||
|
rvol.c \
|
||||||
bi2a-sdvx.c \
|
bi2a-sdvx.c \
|
||||||
main.c \
|
main.c \
|
||||||
|
|||||||
@@ -8,22 +8,24 @@
|
|||||||
|
|
||||||
#include "bio2drv/bi2a-sdvx.h"
|
#include "bio2drv/bi2a-sdvx.h"
|
||||||
|
|
||||||
bool aciotest_bi2a_sdvx_handler_init(uint8_t node_id, void **ctx)
|
bool aciotest_bi2a_sdvx_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
|
||||||
{
|
{
|
||||||
*ctx = malloc(sizeof(uint32_t));
|
*ctx = malloc(sizeof(uint32_t));
|
||||||
*((uint32_t *) *ctx) = 0;
|
*((uint32_t *) *ctx) = 0;
|
||||||
|
|
||||||
return bio2drv_bi2a_sdvx_init(node_id);
|
return bio2drv_bi2a_sdvx_init(device, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciotest_bi2a_sdvx_handler_update(uint8_t node_id, void *ctx)
|
bool aciotest_bi2a_sdvx_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
|
||||||
{
|
{
|
||||||
struct bi2a_sdvx_state_in pin;
|
struct bi2a_sdvx_state_in pin;
|
||||||
struct bi2a_sdvx_state_out pout;
|
struct bi2a_sdvx_state_out pout;
|
||||||
|
|
||||||
memset(&pout, 0, sizeof(pout));
|
memset(&pout, 0, sizeof(pout));
|
||||||
|
|
||||||
if (!bio2drv_bi2a_sdvx_poll(node_id, &pout, &pin)) {
|
if (!bio2drv_bi2a_sdvx_poll(device, node_id, &pout, &pin)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
bool aciotest_bi2a_sdvx_handler_init(uint8_t node_id, void **ctx);
|
#include "aciodrv/device.h"
|
||||||
bool aciotest_bi2a_sdvx_handler_update(uint8_t node_id, void *ctx);
|
|
||||||
|
bool aciotest_bi2a_sdvx_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool aciotest_bi2a_sdvx_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef ACIOTEST_HANDLER_H
|
#ifndef ACIOTEST_HANDLER_H
|
||||||
#define ACIOTEST_HANDLER_H
|
#define ACIOTEST_HANDLER_H
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
static const uint8_t aciotest_handler_max = 16;
|
static const uint8_t aciotest_handler_max = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,8 +10,10 @@ static const uint8_t aciotest_handler_max = 16;
|
|||||||
*/
|
*/
|
||||||
struct aciotest_handler_node_handler {
|
struct aciotest_handler_node_handler {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
bool (*init)(uint8_t node_id, void **ctx);
|
bool (*init)(
|
||||||
bool (*update)(uint8_t node_id, void *ctx);
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool (*update)(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -5,29 +5,52 @@
|
|||||||
|
|
||||||
#include "aciodrv/icca.h"
|
#include "aciodrv/icca.h"
|
||||||
|
|
||||||
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx)
|
|
||||||
{
|
|
||||||
*ctx = malloc(sizeof(uint32_t));
|
|
||||||
*((uint32_t *) *ctx) = 0;
|
|
||||||
|
|
||||||
return aciodrv_icca_init(node_id);
|
#define IDLE_RESPONSES_BETWEEN_FELICA_POLLS 5
|
||||||
|
|
||||||
|
struct icca_handler_ctx {
|
||||||
|
bool init;
|
||||||
|
bool slotted_reader;
|
||||||
|
uint8_t last_poll;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool aciotest_icca_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
|
||||||
|
{
|
||||||
|
*ctx = malloc(sizeof(struct icca_handler_ctx));
|
||||||
|
|
||||||
|
struct icca_handler_ctx *icca_ctx = (struct icca_handler_ctx*)*ctx;
|
||||||
|
icca_ctx->init = false;
|
||||||
|
|
||||||
|
icca_ctx->slotted_reader = true;
|
||||||
|
|
||||||
|
icca_ctx->last_poll = 0;
|
||||||
|
|
||||||
|
icca_ctx->slotted_reader = aciodrv_icca_is_slotted(device, node_id);
|
||||||
|
|
||||||
|
return aciodrv_icca_init(device, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
|
bool aciotest_icca_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
|
||||||
{
|
{
|
||||||
if (*((uint32_t *) ctx) == 0) {
|
struct icca_handler_ctx *icca_ctx = (struct icca_handler_ctx*)ctx;
|
||||||
*((uint32_t *) ctx) = 1;
|
|
||||||
|
|
||||||
/* eject cards that were left in the reader */
|
if (icca_ctx->init == false) {
|
||||||
if (!aciodrv_icca_set_state(
|
icca_ctx->init = true;
|
||||||
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
|
||||||
return false;
|
if (icca_ctx->slotted_reader) {
|
||||||
|
/* eject cards that were left in the reader */
|
||||||
|
if (!aciodrv_icca_set_state(
|
||||||
|
device, node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ac_io_icca_state state;
|
struct ac_io_icca_state state;
|
||||||
|
|
||||||
if (!aciodrv_icca_get_state(node_id, &state)) {
|
if (!aciodrv_icca_get_state(device, node_id, &state)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,33 +81,48 @@ bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
|
|||||||
state.key_events[0],
|
state.key_events[0],
|
||||||
state.key_events[1]);
|
state.key_events[1]);
|
||||||
|
|
||||||
/* eject card with "empty" key */
|
if (icca_ctx->slotted_reader) {
|
||||||
if (state.key_state & AC_IO_ICCA_KEYPAD_MASK_EMPTY) {
|
/* eject card with "empty" key */
|
||||||
if (!aciodrv_icca_set_state(
|
if (state.key_state & AC_IO_ICCA_KEYPAD_MASK_EMPTY) {
|
||||||
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
|
if (!aciodrv_icca_set_state(
|
||||||
return false;
|
device, 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)) {
|
|
||||||
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)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aciodrv_icca_read_card(node_id, NULL)) {
|
/* allow new card to be inserted when slot is clear */
|
||||||
return false;
|
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(
|
||||||
|
device, 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(
|
||||||
|
device, node_id, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aciodrv_icca_read_card(device, node_id, NULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// wavepass reader, see eamio-icca for why this is done this way
|
||||||
|
if (state.status_code != AC_IO_ICCA_STATUS_BUSY_NEW) {
|
||||||
|
++icca_ctx->last_poll;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icca_ctx->last_poll >= IDLE_RESPONSES_BETWEEN_FELICA_POLLS) {
|
||||||
|
if (!aciodrv_icca_poll_felica(device, node_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
icca_ctx->last_poll = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx);
|
#include "aciodrv/device.h"
|
||||||
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx);
|
|
||||||
|
bool aciotest_icca_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool aciotest_icca_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,15 +8,17 @@
|
|||||||
|
|
||||||
#include "aciodrv/kfca.h"
|
#include "aciodrv/kfca.h"
|
||||||
|
|
||||||
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx)
|
bool aciotest_kfca_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
|
||||||
{
|
{
|
||||||
*ctx = malloc(sizeof(uint32_t));
|
*ctx = malloc(sizeof(uint32_t));
|
||||||
*((uint32_t *) *ctx) = 0;
|
*((uint32_t *) *ctx) = 0;
|
||||||
|
|
||||||
return aciodrv_kfca_init(node_id);
|
return aciodrv_kfca_init(device, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
|
bool aciotest_kfca_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
|
||||||
{
|
{
|
||||||
struct ac_io_kfca_poll_in pin;
|
struct ac_io_kfca_poll_in pin;
|
||||||
struct ac_io_kfca_poll_out pout;
|
struct ac_io_kfca_poll_out pout;
|
||||||
@@ -28,7 +30,7 @@ bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
|
|||||||
pout.gpio |= 1 << gpio_test_pin;
|
pout.gpio |= 1 << gpio_test_pin;
|
||||||
pout.gpio = ac_io_u32(pout.gpio);
|
pout.gpio = ac_io_u32(pout.gpio);
|
||||||
|
|
||||||
if (!aciodrv_kfca_poll(node_id, &pout, &pin)) {
|
if (!aciodrv_kfca_poll(device, node_id, &pout, &pin)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx);
|
#include "aciodrv/device.h"
|
||||||
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx);
|
|
||||||
|
bool aciotest_kfca_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool aciotest_kfca_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "aciotest/handler.h"
|
#include "aciotest/handler.h"
|
||||||
#include "aciotest/icca.h"
|
#include "aciotest/icca.h"
|
||||||
#include "aciotest/kfca.h"
|
#include "aciotest/kfca.h"
|
||||||
|
#include "aciotest/panb.h"
|
||||||
|
#include "aciotest/rvol.h"
|
||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
@@ -20,24 +22,37 @@ static uint8_t bi2a_mode = 0;
|
|||||||
* Enumerate supported ACIO nodes based on their product id.
|
* Enumerate supported ACIO nodes based on their product id.
|
||||||
*/
|
*/
|
||||||
static bool aciotest_assign_handler(
|
static bool aciotest_assign_handler(
|
||||||
char product[4], struct aciotest_handler_node_handler *handler)
|
uint32_t product_type, struct aciotest_handler_node_handler *handler)
|
||||||
{
|
{
|
||||||
if (!memcmp(product, "ICCA", 4) || !memcmp(product, "ICCB", 4) ||
|
if (product_type == AC_IO_NODE_TYPE_ICCA) {
|
||||||
!memcmp(product, "ICCC", 4)) {
|
|
||||||
handler->init = aciotest_icca_handler_init;
|
handler->init = aciotest_icca_handler_init;
|
||||||
handler->update = aciotest_icca_handler_update;
|
handler->update = aciotest_icca_handler_update;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(product, "KFCA", 4)) {
|
if (product_type == AC_IO_NODE_TYPE_KFCA) {
|
||||||
handler->init = aciotest_kfca_handler_init;
|
handler->init = aciotest_kfca_handler_init;
|
||||||
handler->update = aciotest_kfca_handler_update;
|
handler->update = aciotest_kfca_handler_update;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(product, "BI2A", 4)) {
|
if (product_type == AC_IO_NODE_TYPE_PANB) {
|
||||||
|
handler->init = aciotest_panb_handler_init;
|
||||||
|
handler->update = aciotest_panb_handler_update;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (product_type == AC_IO_NODE_TYPE_RVOL) {
|
||||||
|
handler->init = aciotest_rvol_handler_init;
|
||||||
|
handler->update = aciotest_rvol_handler_update;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (product_type == AC_IO_NODE_TYPE_BI2A) {
|
||||||
if (bi2a_mode == 0) {
|
if (bi2a_mode == 0) {
|
||||||
handler->init = aciotest_bi2a_sdvx_handler_init;
|
handler->init = aciotest_bi2a_sdvx_handler_init;
|
||||||
handler->update = aciotest_bi2a_sdvx_handler_update;
|
handler->update = aciotest_bi2a_sdvx_handler_update;
|
||||||
@@ -70,14 +85,17 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
log_to_writer(log_writer_stdout, NULL);
|
log_to_writer(log_writer_stdout, NULL);
|
||||||
|
|
||||||
if (!aciodrv_device_open(argv[1], atoi(argv[2]))) {
|
|
||||||
|
struct aciodrv_device_ctx *device = aciodrv_device_open_path(argv[1], atoi(argv[2]));
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
printf("Opening acio device failed\n");
|
printf("Opening acio device failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Opening acio device successful\n");
|
printf("Opening acio device successful\n");
|
||||||
|
|
||||||
uint8_t node_count = aciodrv_device_get_node_count();
|
uint8_t node_count = aciodrv_device_get_node_count(device);
|
||||||
printf("Enumerated %d nodes\n", node_count);
|
printf("Enumerated %d nodes\n", node_count);
|
||||||
|
|
||||||
struct aciotest_handler_node_handler handler[aciotest_handler_max];
|
struct aciotest_handler_node_handler handler[aciotest_handler_max];
|
||||||
@@ -88,29 +106,29 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < node_count; i++) {
|
for (uint8_t i = 0; i < node_count; i++) {
|
||||||
char product[4];
|
char product[4];
|
||||||
aciodrv_device_get_node_product_ident(i, product);
|
uint32_t product_type = aciodrv_device_get_node_product_type(device, i);
|
||||||
|
aciodrv_device_get_node_product_ident(device, i, product);
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"> %d: %c%c%c%c\n",
|
"> %d: %c%c%c%c (%08x)\n",
|
||||||
i + 1,
|
i + 1,
|
||||||
product[0],
|
product[0],
|
||||||
product[1],
|
product[1],
|
||||||
product[2],
|
product[2],
|
||||||
product[3]);
|
product[3],
|
||||||
|
product_type);
|
||||||
|
|
||||||
if (!aciotest_assign_handler(product, &handler[i])) {
|
if (!aciotest_assign_handler(product_type, &handler[i])) {
|
||||||
printf(
|
printf(
|
||||||
"ERROR: Unsupported acio node product %c%c%c%c on node %d\n",
|
"ERROR: Unsupported acio node product %08x on node %d\n",
|
||||||
product[0],
|
product_type,
|
||||||
product[1],
|
|
||||||
product[2],
|
|
||||||
product[3],
|
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
||||||
if (handler[i].init != NULL) {
|
if (handler[i].init != NULL) {
|
||||||
if (!handler[i].init(i, &handler[i].ctx)) {
|
if (!handler[i].init(device, i, &handler[i].ctx)) {
|
||||||
printf("ERROR: Initializing node %d failed\n", i);
|
printf("ERROR: Initializing node %d failed\n", i);
|
||||||
handler[i].update = NULL;
|
handler[i].update = NULL;
|
||||||
}
|
}
|
||||||
@@ -129,7 +147,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
|
||||||
if (handler[i].update != NULL) {
|
if (handler[i].update != NULL) {
|
||||||
if (!handler[i].update(i, handler[i].ctx)) {
|
if (!handler[i].update(device, i, handler[i].ctx)) {
|
||||||
printf("ERROR: Updating node %d, removed from loop\n", i);
|
printf("ERROR: Updating node %d, removed from loop\n", i);
|
||||||
handler[i].update = NULL;
|
handler[i].update = NULL;
|
||||||
Sleep(5000);
|
Sleep(5000);
|
||||||
|
|||||||
76
src/main/aciotest/panb.c
Normal file
76
src/main/aciotest/panb.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include "aciotest/panb.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "aciodrv/panb.h"
|
||||||
|
#include "aciodrv-proc/panb.h"
|
||||||
|
|
||||||
|
struct panb_handler_ctx {
|
||||||
|
bool running;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool aciotest_panb_handler_init(struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
|
||||||
|
{
|
||||||
|
if (node_id != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ctx = malloc(sizeof(struct panb_handler_ctx));
|
||||||
|
struct panb_handler_ctx *panb_ctx = (struct panb_handler_ctx*)*ctx;
|
||||||
|
panb_ctx->running = true;
|
||||||
|
|
||||||
|
return aciodrv_proc_panb_init(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciotest_panb_handler_update(struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
|
||||||
|
{
|
||||||
|
uint8_t button[AC_IO_PANB_MAX_KEYS];
|
||||||
|
struct ac_io_panb_poll_out state;
|
||||||
|
struct panb_handler_ctx *panb_ctx = (struct panb_handler_ctx *) ctx;
|
||||||
|
|
||||||
|
if (node_id != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!panb_ctx->running) {
|
||||||
|
printf(">>> PANB:\nDevice has been closed. Press Ctrl+C to exit.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aciodrv_proc_panb_get_state(button)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(">>> PANB:\nPress first and last keys to close device\n");
|
||||||
|
|
||||||
|
for (int i=0; i<AC_IO_PANB_MAX_KEYS; i++) {
|
||||||
|
printf("%01X ", button[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
/* I added a key combo to properly close the module.
|
||||||
|
* Leaving the PANB device in autopolling state without ever
|
||||||
|
* reading packets from the serial interface eventually
|
||||||
|
* makes it fall into a state where it doesn't send anything anymore
|
||||||
|
* and won't even respond to a reset, thus requiring a power cycle.
|
||||||
|
*/
|
||||||
|
if (button[0] && button[AC_IO_PANB_MAX_KEYS-1]) {
|
||||||
|
aciodrv_proc_panb_fini(device);
|
||||||
|
panb_ctx->running = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* light the panel */
|
||||||
|
for (int i=0; i<AC_IO_PANB_MAX_KEYS; i++) {
|
||||||
|
state.key[i].green = (button[i])? 0x7F : 0;
|
||||||
|
state.key[i].red = 0;
|
||||||
|
state.key[i].blue = (button[i])? 0x23 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aciodrv_panb_send_lamp(device, node_id, &state)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
12
src/main/aciotest/panb.h
Normal file
12
src/main/aciotest/panb.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef ACIOTEST_PANB_H
|
||||||
|
#define ACIOTEST_PANB_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
|
bool aciotest_panb_handler_init(struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool aciotest_panb_handler_update(struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
73
src/main/aciotest/rvol.c
Normal file
73
src/main/aciotest/rvol.c
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include "aciotest/rvol.h"
|
||||||
|
|
||||||
|
#include "acio/acio.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "aciodrv/rvol.h"
|
||||||
|
|
||||||
|
static struct ac_io_rvol_poll_out pout;
|
||||||
|
|
||||||
|
bool aciotest_rvol_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
|
||||||
|
{
|
||||||
|
memset(&pout, 0, sizeof(pout));
|
||||||
|
return aciodrv_rvol_init(device, node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aciotest_rvol_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
|
||||||
|
{
|
||||||
|
struct ac_io_rvol_poll_in pin;
|
||||||
|
|
||||||
|
if (!aciodrv_rvol_poll(device, node_id, &pout, &pin)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t selected_light = pin.spinners[0] / 43;
|
||||||
|
|
||||||
|
printf(
|
||||||
|
">>> RVOL %d\n"
|
||||||
|
"Press: %3d %3d %3d\n"
|
||||||
|
" %3d %3d\n"
|
||||||
|
"\n"
|
||||||
|
"Spin: %3d %3d %3d\n"
|
||||||
|
" %3d %3d\n"
|
||||||
|
"\n"
|
||||||
|
"Pedal: %3d\n"
|
||||||
|
"\n"
|
||||||
|
"Editing light #%d R: %d G: %d B: %d\n"
|
||||||
|
"(Change light with Spinner 1, values with 3-5)\n",
|
||||||
|
node_id,
|
||||||
|
pin.buttons_2.spinner_1,
|
||||||
|
pin.buttons_3.spinner_3,
|
||||||
|
pin.buttons_1.spinner_5,
|
||||||
|
pin.buttons_2.spinner_2,
|
||||||
|
pin.buttons_1.spinner_4,
|
||||||
|
pin.spinners[0],
|
||||||
|
pin.spinners[2],
|
||||||
|
pin.spinners[4],
|
||||||
|
pin.spinners[1],
|
||||||
|
pin.spinners[3],
|
||||||
|
!pin.buttons_1.pedal,
|
||||||
|
selected_light,
|
||||||
|
pin.spinners[2] / 2,
|
||||||
|
pin.spinners[3] / 2,
|
||||||
|
pin.spinners[4] / 2
|
||||||
|
);
|
||||||
|
|
||||||
|
memset(&pout, 0, sizeof(pout));
|
||||||
|
|
||||||
|
if (selected_light == 5) {
|
||||||
|
pout.title.r = pin.spinners[2] / 2;
|
||||||
|
pout.title.g = pin.spinners[3] / 2;
|
||||||
|
pout.title.b = pin.spinners[4] / 2;
|
||||||
|
} else {
|
||||||
|
pout.spinner[selected_light].r = pin.spinners[2] / 2;
|
||||||
|
pout.spinner[selected_light].g = pin.spinners[3] / 2;
|
||||||
|
pout.spinner[selected_light].b = pin.spinners[4] / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
14
src/main/aciotest/rvol.h
Normal file
14
src/main/aciotest/rvol.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef ACIOTEST_RVOL_H
|
||||||
|
#define ACIOTEST_RVOL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
|
bool aciotest_rvol_handler_init(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
|
||||||
|
bool aciotest_rvol_handler_update(
|
||||||
|
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -29,6 +29,17 @@ enum jb_io_panel_bit {
|
|||||||
JB_IO_PANEL_16 = 0x0F,
|
JB_IO_PANEL_16 = 0x0F,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* input "single button mode" mappings. Allows you to check each corner of each
|
||||||
|
button to determine any flaky inputs
|
||||||
|
*/
|
||||||
|
enum jb_io_panel_mode {
|
||||||
|
JB_IO_PANEL_MODE_ALL = 0, // any of the four corners will trigger a panel
|
||||||
|
JB_IO_PANEL_MODE_TOP_LEFT = 1,
|
||||||
|
JB_IO_PANEL_MODE_TOP_RIGHT = 2,
|
||||||
|
JB_IO_PANEL_MODE_BOTTOM_RIGHT = 3,
|
||||||
|
JB_IO_PANEL_MODE_BOTTOM_LEFT = 4,
|
||||||
|
};
|
||||||
|
|
||||||
/* Bit mappings for "system" inputs */
|
/* Bit mappings for "system" inputs */
|
||||||
enum jb_io_sys_bit {
|
enum jb_io_sys_bit {
|
||||||
JB_IO_SYS_TEST = 0x00,
|
JB_IO_SYS_TEST = 0x00,
|
||||||
@@ -73,17 +84,36 @@ bool jb_io_init(
|
|||||||
|
|
||||||
void jb_io_fini(void);
|
void jb_io_fini(void);
|
||||||
|
|
||||||
/* TODO doc */
|
/* Read input state */
|
||||||
|
|
||||||
bool jb_io_read_inputs(void);
|
bool jb_io_read_inputs(void);
|
||||||
|
|
||||||
bool jb_io_write_outputs(void);
|
/* Get state of coin, test, service inputs */
|
||||||
|
|
||||||
uint8_t jb_io_get_sys_inputs(void);
|
uint8_t jb_io_get_sys_inputs(void);
|
||||||
|
|
||||||
|
/* Get panel button state. Will return either any button being pressed, or a
|
||||||
|
particular panel corner depending on previous call to jb_io_set_panel_mode */
|
||||||
|
|
||||||
uint16_t jb_io_get_panel_inputs(void);
|
uint16_t jb_io_get_panel_inputs(void);
|
||||||
|
|
||||||
|
/* Set state of a PWM (dimmable) light */
|
||||||
|
|
||||||
void jb_io_set_rgb_led(
|
void jb_io_set_rgb_led(
|
||||||
enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b);
|
enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
|
||||||
|
/* Transmit the light state to the IOPCB */
|
||||||
|
|
||||||
|
bool jb_io_write_lights(void);
|
||||||
|
|
||||||
|
/* Select operating mode for the panel. Should be immediately sent to the IOPCB */
|
||||||
|
|
||||||
|
bool jb_io_set_panel_mode(enum jb_io_panel_mode mode);
|
||||||
|
|
||||||
|
/* Open or close the coin chute - true will redirect all coins to the return
|
||||||
|
slot. Required for jb_io_set_panel_mode to operate correctly on p4io.
|
||||||
|
Should be immediately sent to the IOPCB */
|
||||||
|
|
||||||
|
bool jb_io_set_coin_blocker(bool blocked);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
56
src/main/bio2/bi2a-ddr.h
Normal file
56
src/main/bio2/bi2a-ddr.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef BIO2_BI2A_DDR
|
||||||
|
#define BIO2_BI2A_DDR
|
||||||
|
|
||||||
|
#include "bio2/bio2.h"
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
struct bi2a_ddr_system_panel {
|
||||||
|
uint8_t b_unk1 : 1;
|
||||||
|
uint8_t b_coin : 1;
|
||||||
|
uint8_t b_service : 1;
|
||||||
|
uint8_t b_test : 1;
|
||||||
|
uint8_t b_un2 : 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bi2a_ddr_player_1_panel {
|
||||||
|
uint8_t b_unk : 3;
|
||||||
|
uint8_t b_right : 1;
|
||||||
|
uint8_t b_left : 1;
|
||||||
|
uint8_t b_down : 1;
|
||||||
|
uint8_t b_up : 1;
|
||||||
|
uint8_t b_start : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bi2a_ddr_player_2_panel {
|
||||||
|
uint8_t b_unk1 : 1;
|
||||||
|
uint8_t b_right : 1;
|
||||||
|
uint8_t b_left : 1;
|
||||||
|
uint8_t b_down : 1;
|
||||||
|
uint8_t b_up : 1;
|
||||||
|
uint8_t b_start : 1;
|
||||||
|
uint8_t b_unk2 : 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bi2a_ddr_state_in {
|
||||||
|
uint8_t unk1;
|
||||||
|
struct bi2a_ddr_system_panel system;
|
||||||
|
uint8_t unk2[7];
|
||||||
|
struct bi2a_ddr_player_1_panel player_1;
|
||||||
|
struct bi2a_ddr_player_2_panel player_2;
|
||||||
|
uint8_t unk3[5];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bi2a_ddr_state_out {
|
||||||
|
uint8_t unk1[40];
|
||||||
|
};
|
||||||
|
|
||||||
|
_Static_assert(
|
||||||
|
sizeof(struct bi2a_ddr_state_in) == 16,
|
||||||
|
"bi2a_ddr_state_in is the wrong size");
|
||||||
|
_Static_assert(
|
||||||
|
sizeof(struct bi2a_ddr_state_out) == 40,
|
||||||
|
"bi2a_ddr_state_out is the wrong size");
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -11,6 +11,11 @@ enum bio2_bi2a_cmd {
|
|||||||
BIO2_BI2A_CMD_INIT = 0x0100,
|
BIO2_BI2A_CMD_INIT = 0x0100,
|
||||||
BIO2_BI2A_CMD_WATCHDOG = 0x0120,
|
BIO2_BI2A_CMD_WATCHDOG = 0x0120,
|
||||||
BIO2_BI2A_CMD_POLL = 0x0152, // For IIDX
|
BIO2_BI2A_CMD_POLL = 0x0152, // For IIDX
|
||||||
|
// For games using libacio for BIO2 communication
|
||||||
|
BIO2_BI2A_CMD_ACIO_POLL_NOWD = 0x0112,
|
||||||
|
BIO2_BI2A_CMD_ACIO_POLL_WD = 0x0113,
|
||||||
|
BIO2_BI2A_CMD_TAPELED_INIT = 0x0140,
|
||||||
|
BIO2_BI2A_CMD_TAPELED_SEND = 0x0141,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -14,17 +14,23 @@
|
|||||||
// in all inputs and outputs (over sub IO) other than 14 keys to not work.
|
// in all inputs and outputs (over sub IO) other than 14 keys to not work.
|
||||||
static const uint8_t _BIO2DR_BI2A_IIDX_INIT_DATA = 0x2D;
|
static const uint8_t _BIO2DR_BI2A_IIDX_INIT_DATA = 0x2D;
|
||||||
|
|
||||||
static bool bio2drv_bi2a_iidx_init_io(uint8_t node_id)
|
static bool bio2drv_bi2a_iidx_init_io(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
||||||
msg.cmd.nbytes = 1;
|
msg.cmd.nbytes = 1;
|
||||||
msg.cmd.param = _BIO2DR_BI2A_IIDX_INIT_DATA;
|
msg.cmd.param = _BIO2DR_BI2A_IIDX_INIT_DATA;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Init node failed");
|
log_warning("Init node failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -34,8 +40,12 @@ static bool bio2drv_bi2a_iidx_init_io(uint8_t node_id)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bio2drv_bi2a_iidx_watchdog_start(uint8_t node_id)
|
static bool bio2drv_bi2a_iidx_watchdog_start(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id)
|
||||||
{
|
{
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
// exit early and don't actually call watchdog
|
// exit early and don't actually call watchdog
|
||||||
// the watchdog call actually returns different sized packets depending on
|
// the watchdog call actually returns different sized packets depending on
|
||||||
// the state this results in an issue during packet processing (see: #68)
|
// the state this results in an issue during packet processing (see: #68)
|
||||||
@@ -47,14 +57,13 @@ static bool bio2drv_bi2a_iidx_watchdog_start(uint8_t node_id)
|
|||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
|
||||||
msg.cmd.nbytes = 2;
|
msg.cmd.nbytes = 2;
|
||||||
msg.cmd.nbytes = 2;
|
|
||||||
|
|
||||||
// uint16_t: 6000
|
// uint16_t: 6000
|
||||||
msg.cmd.raw[0] = 23;
|
msg.cmd.raw[0] = 23;
|
||||||
msg.cmd.raw[1] = 112;
|
msg.cmd.raw[1] = 112;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 2
|
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 2
|
||||||
)) {
|
)) {
|
||||||
log_warning("Starting watchdog failed"); return false;
|
log_warning("Starting watchdog failed"); return false;
|
||||||
}
|
}
|
||||||
@@ -66,13 +75,15 @@ static bool bio2drv_bi2a_iidx_watchdog_start(uint8_t node_id)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bio2drv_bi2a_iidx_init(uint8_t node_id)
|
bool bio2drv_bi2a_iidx_init(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
if (!bio2drv_bi2a_iidx_init_io(node_id)) {
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!bio2drv_bi2a_iidx_init_io(device, node_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bio2drv_bi2a_iidx_watchdog_start(node_id)) {
|
if (!bio2drv_bi2a_iidx_watchdog_start(device, node_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +91,15 @@ bool bio2drv_bi2a_iidx_init(uint8_t node_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bio2drv_bi2a_iidx_poll(
|
bool bio2drv_bi2a_iidx_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct bi2a_iidx_state_out *pout,
|
const struct bi2a_iidx_state_out *pout,
|
||||||
struct bi2a_iidx_state_in *pin)
|
struct bi2a_iidx_state_in *pin)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
// log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_POLL);
|
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_POLL);
|
||||||
msg.cmd.nbytes = sizeof(*pout);
|
msg.cmd.nbytes = sizeof(*pout);
|
||||||
@@ -93,7 +107,9 @@ bool bio2drv_bi2a_iidx_poll(
|
|||||||
*(struct bi2a_iidx_state_out *) msg.cmd.raw = *pout;
|
*(struct bi2a_iidx_state_out *) msg.cmd.raw = *pout;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||||
log_warning("Polling of node %d failed", node_id + 1);
|
log_warning("Polling of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
#ifndef BIO2DRV_BI2A_IIDX_H
|
#ifndef BIO2DRV_BI2A_IIDX_H
|
||||||
#define BIO2DRV_BI2A_IIDX_H
|
#define BIO2DRV_BI2A_IIDX_H
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
#include "bio2/bi2a-iidx.h"
|
#include "bio2/bi2a-iidx.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a BI2A node.
|
* Initialize a BI2A node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to initialize (0 based).
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
* @return True if successful, false on error.
|
* @return True if successful, false on error.
|
||||||
* @note This module is supposed to be used in combination with the common
|
* @note This module is supposed to be used in combination with the common
|
||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool bio2drv_bi2a_iidx_init(uint8_t node_id);
|
bool bio2drv_bi2a_iidx_init(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll the BI2A board
|
* Poll the BI2A board
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
* (optional, NULL for none).
|
* (optional, NULL for none).
|
||||||
@@ -26,6 +32,7 @@ bool bio2drv_bi2a_iidx_init(uint8_t node_id);
|
|||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool bio2drv_bi2a_iidx_poll(
|
bool bio2drv_bi2a_iidx_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct bi2a_iidx_state_out *pout,
|
const struct bi2a_iidx_state_out *pout,
|
||||||
struct bi2a_iidx_state_in *pin);
|
struct bi2a_iidx_state_in *pin);
|
||||||
|
|||||||
@@ -12,17 +12,21 @@
|
|||||||
static const uint8_t _BIO2DR_BI2A_SDVX_INIT_DATA = 0x3B;
|
static const uint8_t _BIO2DR_BI2A_SDVX_INIT_DATA = 0x3B;
|
||||||
|
|
||||||
// this is probably InitIO
|
// this is probably InitIO
|
||||||
static bool bio2drv_bi2a_sdvx_init_io(uint8_t node_id)
|
static bool bio2drv_bi2a_sdvx_init_io(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
||||||
msg.cmd.nbytes = 1;
|
msg.cmd.nbytes = 1;
|
||||||
msg.cmd.param = _BIO2DR_BI2A_SDVX_INIT_DATA;
|
msg.cmd.param = _BIO2DR_BI2A_SDVX_INIT_DATA;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Init node failed");
|
log_warning("Init node failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -32,8 +36,10 @@ static bool bio2drv_bi2a_sdvx_init_io(uint8_t node_id)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
|
static bool bio2drv_bi2a_sdvx_watchdog_start(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
// exit early and don't actually call watchdog
|
// exit early and don't actually call watchdog
|
||||||
// the watchdog call actually returns different sized packets depending on
|
// the watchdog call actually returns different sized packets depending on
|
||||||
// the state this results in an issue during packet processing (see: #68)
|
// the state this results in an issue during packet processing (see: #68)
|
||||||
@@ -52,7 +58,7 @@ static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
|
|||||||
msg.cmd.raw[1] = 112;
|
msg.cmd.raw[1] = 112;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 2
|
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 2
|
||||||
)) {
|
)) {
|
||||||
log_warning("Starting watchdog failed"); return false;
|
log_warning("Starting watchdog failed"); return false;
|
||||||
}
|
}
|
||||||
@@ -65,6 +71,7 @@ static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bio2drv_bi2a_sdvx_amp(
|
bool bio2drv_bi2a_sdvx_amp(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
uint8_t unused_1,
|
uint8_t unused_1,
|
||||||
uint8_t unused_2,
|
uint8_t unused_2,
|
||||||
@@ -73,6 +80,8 @@ bool bio2drv_bi2a_sdvx_amp(
|
|||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
|
||||||
msg.cmd.nbytes = 4;
|
msg.cmd.nbytes = 4;
|
||||||
@@ -86,7 +95,9 @@ bool bio2drv_bi2a_sdvx_amp(
|
|||||||
msg.cmd.raw[3] = right;
|
msg.cmd.raw[3] = right;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||||
log_warning("Setting AMP failed");
|
log_warning("Setting AMP failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -96,17 +107,19 @@ bool bio2drv_bi2a_sdvx_amp(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bio2drv_bi2a_sdvx_init(uint8_t node_id)
|
bool bio2drv_bi2a_sdvx_init(struct aciodrv_device_ctx *device, uint8_t node_id)
|
||||||
{
|
{
|
||||||
if (!bio2drv_bi2a_sdvx_init_io(node_id)) {
|
log_assert(device);
|
||||||
|
|
||||||
|
if (!bio2drv_bi2a_sdvx_init_io(device, node_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bio2drv_bi2a_sdvx_watchdog_start(node_id)) {
|
if (!bio2drv_bi2a_sdvx_watchdog_start(device, node_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bio2drv_bi2a_sdvx_amp(node_id, 0, 0, 0, 0)) {
|
if (!bio2drv_bi2a_sdvx_amp(device, node_id, 0, 0, 0, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,12 +127,15 @@ bool bio2drv_bi2a_sdvx_init(uint8_t node_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool bio2drv_bi2a_sdvx_poll(
|
bool bio2drv_bi2a_sdvx_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct bi2a_sdvx_state_out *pout,
|
const struct bi2a_sdvx_state_out *pout,
|
||||||
struct bi2a_sdvx_state_in *pin)
|
struct bi2a_sdvx_state_in *pin)
|
||||||
{
|
{
|
||||||
struct ac_io_message msg;
|
struct ac_io_message msg;
|
||||||
|
|
||||||
|
// log_assert(device);
|
||||||
|
|
||||||
msg.addr = node_id + 1;
|
msg.addr = node_id + 1;
|
||||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
|
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
|
||||||
msg.cmd.nbytes = sizeof(*pout);
|
msg.cmd.nbytes = sizeof(*pout);
|
||||||
@@ -127,7 +143,9 @@ bool bio2drv_bi2a_sdvx_poll(
|
|||||||
*(struct bi2a_sdvx_state_out *) msg.cmd.raw = *pout;
|
*(struct bi2a_sdvx_state_out *) msg.cmd.raw = *pout;
|
||||||
|
|
||||||
if (!aciodrv_send_and_recv(
|
if (!aciodrv_send_and_recv(
|
||||||
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
device,
|
||||||
|
&msg,
|
||||||
|
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||||
log_warning("Polling of node %d failed", node_id + 1);
|
log_warning("Polling of node %d failed", node_id + 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
#ifndef BIO2DRV_BI2A_H
|
#ifndef BIO2DRV_BI2A_SDVX_H
|
||||||
#define BIO2DRV_BI2A_H
|
#define BIO2DRV_BI2A_SDVX_H
|
||||||
|
|
||||||
|
#include "aciodrv/device.h"
|
||||||
|
|
||||||
#include "bio2/bi2a-sdvx.h"
|
#include "bio2/bi2a-sdvx.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a BI2A node.
|
* Initialize a BI2A node.
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to initialize (0 based).
|
* @param node_id Id of the node to initialize (0 based).
|
||||||
* @return True if successful, false on error.
|
* @return True if successful, false on error.
|
||||||
* @note This module is supposed to be used in combination with the common
|
* @note This module is supposed to be used in combination with the common
|
||||||
* device driver foundation.
|
* device driver foundation.
|
||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool bio2drv_bi2a_sdvx_init(uint8_t node_id);
|
bool bio2drv_bi2a_sdvx_init(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
|
uint8_t node_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll the board
|
* Poll the board
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param state Pointer to a state struct to return the current state to
|
* @param state Pointer to a state struct to return the current state to
|
||||||
* (optional, NULL for none).
|
* (optional, NULL for none).
|
||||||
@@ -26,6 +32,7 @@ bool bio2drv_bi2a_sdvx_init(uint8_t node_id);
|
|||||||
* @see driver.h
|
* @see driver.h
|
||||||
*/
|
*/
|
||||||
bool bio2drv_bi2a_sdvx_poll(
|
bool bio2drv_bi2a_sdvx_poll(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
const struct bi2a_sdvx_state_out *pout,
|
const struct bi2a_sdvx_state_out *pout,
|
||||||
struct bi2a_sdvx_state_in *pin);
|
struct bi2a_sdvx_state_in *pin);
|
||||||
@@ -33,6 +40,7 @@ bool bio2drv_bi2a_sdvx_poll(
|
|||||||
/**
|
/**
|
||||||
* Set the BIO2 BI2A SDVX digital amp level
|
* Set the BIO2 BI2A SDVX digital amp level
|
||||||
*
|
*
|
||||||
|
* @param device Context of opened device
|
||||||
* @param node_id Id of the node to query (0 based).
|
* @param node_id Id of the node to query (0 based).
|
||||||
* @param primary primary volume (96-0)
|
* @param primary primary volume (96-0)
|
||||||
* @param headphone headphone volume (96-0)
|
* @param headphone headphone volume (96-0)
|
||||||
@@ -42,6 +50,7 @@ bool bio2drv_bi2a_sdvx_poll(
|
|||||||
* @note Note 96 is lowest volume level, 0 is highest
|
* @note Note 96 is lowest volume level, 0 is highest
|
||||||
*/
|
*/
|
||||||
bool bio2drv_bi2a_sdvx_amp(
|
bool bio2drv_bi2a_sdvx_amp(
|
||||||
|
struct aciodrv_device_ctx *device,
|
||||||
uint8_t node_id,
|
uint8_t node_id,
|
||||||
uint8_t unused_1,
|
uint8_t unused_1,
|
||||||
uint8_t unused_2,
|
uint8_t unused_2,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user