From c3f6f8b34f8e36fb40ee4fd55d4fb39ffa2ea287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20R=C3=BCth?= Date: Sun, 10 Dec 2023 19:54:59 +0100 Subject: [PATCH] Use rust --- .github/workflows/build.yaml | 11 +- .github/workflows/ci.yml | 32 + .github/workflows/native.yaml | 24 - .gitignore | 9 +- CMakeLists.txt | 129 --- Cargo.lock | 779 +++++++++++++++ Cargo.toml | 13 + Makefile | 20 + es2button/Cargo.toml | 38 + es2button/src/list.rs | 40 + es2button/src/listener.rs | 186 ++++ es2button/src/main.rs | 61 ++ es2button/src/types.rs | 67 ++ es2command-sys/Cargo.toml | 17 + es2command-sys/build.rs | 89 ++ .../include/ES2Command/ES2CommandAPI.h | 56 ++ .../include/ES2Command/ESCommandProperties.h | 397 ++++++++ .../include/ES2Command/ESPropertyKeys.h | 884 ++++++++++++++++++ .../include/ES2Command/ESResultString.h | 54 ++ .../include/ES2Command/IESScanner.h | 483 ++++++++++ .../cinterface/include/ES2Command/LICENSE | 502 ++++++++++ .../cinterface/include/ES2Command/types.h | 23 + es2command-sys/cinterface/include/common.hpp | 15 + .../cinterface/include/delegate.hpp | 43 + es2command-sys/cinterface/include/scanner.hpp | 83 ++ es2command-sys/cinterface/include/wrapper.hpp | 23 + es2command-sys/cinterface/src/delegate.cpp | 239 +++++ es2command-sys/cinterface/src/internal.hpp | 125 +++ es2command-sys/cinterface/src/scanner.cpp | 387 ++++++++ es2command-sys/cinterface/src/wrapper.cpp | 23 + es2command-sys/src/lib.rs | 5 + es2command/Cargo.toml | 17 + es2command/src/delegate.rs | 369 ++++++++ es2command/src/helper.rs | 8 + es2command/src/lib.rs | 8 + es2command/src/scanner.rs | 349 +++++++ es2command/src/types.rs | 205 ++++ example/example-scanimage.sh | 4 +- src/main.cpp | 448 --------- templates/config.h.in | 2 - 40 files changed, 5649 insertions(+), 618 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/native.yaml delete mode 100644 CMakeLists.txt create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 es2button/Cargo.toml create mode 100644 es2button/src/list.rs create mode 100644 es2button/src/listener.rs create mode 100644 es2button/src/main.rs create mode 100644 es2button/src/types.rs create mode 100644 es2command-sys/Cargo.toml create mode 100644 es2command-sys/build.rs create mode 100644 es2command-sys/cinterface/include/ES2Command/ES2CommandAPI.h create mode 100644 es2command-sys/cinterface/include/ES2Command/ESCommandProperties.h create mode 100644 es2command-sys/cinterface/include/ES2Command/ESPropertyKeys.h create mode 100644 es2command-sys/cinterface/include/ES2Command/ESResultString.h create mode 100644 es2command-sys/cinterface/include/ES2Command/IESScanner.h create mode 100644 es2command-sys/cinterface/include/ES2Command/LICENSE create mode 100644 es2command-sys/cinterface/include/ES2Command/types.h create mode 100644 es2command-sys/cinterface/include/common.hpp create mode 100644 es2command-sys/cinterface/include/delegate.hpp create mode 100644 es2command-sys/cinterface/include/scanner.hpp create mode 100644 es2command-sys/cinterface/include/wrapper.hpp create mode 100644 es2command-sys/cinterface/src/delegate.cpp create mode 100644 es2command-sys/cinterface/src/internal.hpp create mode 100644 es2command-sys/cinterface/src/scanner.cpp create mode 100644 es2command-sys/cinterface/src/wrapper.cpp create mode 100644 es2command-sys/src/lib.rs create mode 100644 es2command/Cargo.toml create mode 100644 es2command/src/delegate.rs create mode 100644 es2command/src/helper.rs create mode 100644 es2command/src/lib.rs create mode 100644 es2command/src/scanner.rs create mode 100644 es2command/src/types.rs delete mode 100644 src/main.cpp delete mode 100644 templates/config.h.in diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2a50241..8756724 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -33,15 +33,16 @@ jobs: # Install dependencies so that they are cached install: | apt-get --quiet update -y - apt-get install -y -q wget cmake file build-essential libboost-dev nlohmann-json3-dev libusb-1.0-0 libusb-1.0-0-dev + apt-get install -y -q libssl-dev pkg-config clang build-essential libusb-1.0-0 libusb-1.0-0-dev + curl https://sh.rustup.rs -sSf | sh -s -- -y + rustup component add rustfmt clippy + cargo install cargo-deb # build run: | - cmake . -B.build - make -C .build -j2 - make -C .build package + make deb - uses: actions/upload-artifact@v3 with: name: packages-${{ matrix.arch }} - path: .build/artifacts/*.deb \ No newline at end of file + path: target/release/debian/*.deb \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..41c56d2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: Rust check + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -Dwarnings + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Install dependencies + run: sudo apt-get install -y libssl-dev pkg-config clang build-essential libusb-1.0-0 libusb-1.0-0-dev + - name: Check fmt + run: make fmt + - name: Lint + run: make lint + - name: Tests usual + run: make test + - name: Build usual + run: make build + - uses: actions/upload-artifact@v3 + with: + name: packages-x86_64 + path: target/release/debian/*.deb \ No newline at end of file diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml deleted file mode 100644 index 41d5600..0000000 --- a/.github/workflows/native.yaml +++ /dev/null @@ -1,24 +0,0 @@ -on: [push, pull_request] - -jobs: - build_job: - # The host should always be linux - runs-on: ubuntu-latest - name: Build on x86_64 - - steps: - # Checkout the repo to $PWD - - uses: actions/checkout@v3 - # Build - - name: Build - run: | - sudo apt-get --quiet update -y - sudo apt-get install -y -q wget cmake file build-essential libboost-dev nlohmann-json3-dev libusb-1.0-0 libusb-1.0-0-dev - cmake . -B.build - make -C .build -j2 - make -C .build package - - - uses: actions/upload-artifact@v3 - with: - name: packages-x86_64 - path: .build/artifacts/*.deb \ No newline at end of file diff --git a/.gitignore b/.gitignore index e2139ed..4ebe4b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,3 @@ -Makefile -epsonscan2-* -CMakeFiles -CMakeCache.txt -cmake_install.cmake -ess2devstate .vscode -build .DS_Store -include/* \ No newline at end of file +target/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 129a4bb..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,129 +0,0 @@ -cmake_minimum_required (VERSION 2.8.12.2) -project (es2button) -set(CMAKE_INSTALL_PREFIX "/usr") -set(CMAKE_PROJECT_VERSION_MAJOR 0) -set(CMAKE_PROJECT_VERSION_MINOR 2) -set(CMAKE_PROJECT_VERSION_PATCH 1) -set(CMAKE_PROJECT_HOMEPAGE_URL "https://github.com/janrueth/es2button") - -# download epson source -set(ESPONVERSION 6.7.43.0-1) -set(ESPONSHA1 0b4e4c2b43e1ef02bf593f3a108e0f78a3b59a0c) -set(EPSONPACKAGE epsonscan2-${ESPONVERSION}) -set(EPSONFILENAME ${EPSONPACKAGE}.src.tar.gz) - -set(CURRENT_EPSONSHA1 "DOES NOT EXIST") -if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${EPSONFILENAME}) - message(" found ${EPSONFILENAME} checking SHA1") - file(SHA1 ${CMAKE_CURRENT_BINARY_DIR}/${EPSONFILENAME} CURRENT_EPSONSHA1) -endif() - -if(NOT ${CURRENT_EPSONSHA1} STREQUAL ${ESPONSHA1}) - message(" ${EPSONFILENAME} does not exist or has invalid sha1, downloading") - file(DOWNLOAD - https://support.epson.net/linux/src/scanner/epsonscan2/${EPSONFILENAME} - ${CMAKE_CURRENT_BINARY_DIR}/${EPSONFILENAME} - SHOW_PROGRESS - ) -endif() - - -set(ES2INCLUDE - "${CMAKE_CURRENT_BINARY_DIR}/epsonscan2" -) -set(ES2MAINHEADER - ${ES2INCLUDE}/Include/ES2Command/ES2CommandAPI.h -) -# we create a command that untar the epson source -add_custom_command(OUTPUT ${ES2MAINHEADER} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - # untar - COMMAND ${CMAKE_COMMAND} -E tar x ${CMAKE_CURRENT_BINARY_DIR}/${EPSONFILENAME} ${EPSONPACKAGE}/src - # cmake's tar can't strip folders so we do that manually by renaming - COMMAND ${CMAKE_COMMAND} -E rename ${EPSONPACKAGE}/src ${ES2INCLUDE} - COMMAND ${CMAKE_COMMAND} -E rm -rf ${EPSONPACKAGE} -) -# we add a target that uses that command -add_custom_target(es2untar DEPENDS ${ES2MAINHEADER}) - - -# we only need some header definition -find_package(Boost 1.36.0 REQUIRED) -message(" Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}") - -find_package(nlohmann_json 3.9.1 REQUIRED) - -find_path(LIBUSB_INCLUDE_DIR - NAMES libusb.h - PATH_SUFFIXES "include" "libusb" "libusb-1.0" - REQUIRED -) - -find_library(LIBUSB_LIBRARY - usb-1.0 - REQUIRED -) - -message(" LIBUSB_LIBRARY: ${LIBUSB_LIBRARY}") -message(" LIBUSB_INCLUDE_DIR: ${LIBUSB_INCLUDE_DIR}") - -# We need to dynamically load libes2command.so but dlopen does not search subfolders -# as such, we just grab the install location that epsonscan2 uses -include(GNUInstallDirs) -set(EPSONSCAN2_LIB_PATH ${CMAKE_INSTALL_FULL_LIBDIR}/epsonscan2/) -message(" EPSONSCAN2_LIB_PATH: ${EPSONSCAN2_LIB_PATH}") -set(ES2CONF_DIR /etc/es2button) - -# we template the config.h.in file to config.h -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/templates/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/config.h) - -include_directories( - ${ES2INCLUDE} - ${Boost_INCLUDE_DIRS} - ${LIBUSB_INCLUDE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/generated - nlohmann_json::nlohmann_json -) - - -add_executable(es2button - ./src/main.cpp -) - -# make sure we've got the epsonscan2 headers when we build es2button -add_dependencies(es2button es2untar) - -target_link_libraries(es2button - PRIVATE nlohmann_json::nlohmann_json # this is a header only library, so no actual linkage - PRIVATE ${CMAKE_DL_LIBS} - PRIVATE ${LIBUSB_LIBRARY} -) - -# this installs es2button -install(TARGETS es2button) -# copy udev rule and make sure it is executed after epsonscan2.rules (60) -install(FILES resources/udev-es2button.rules DESTINATION /lib/udev/rules.d/ RENAME 61-es2button.rules) -# copy systemd rule which is activated by udev -install(FILES resources/systemd.service DESTINATION /lib/systemd/system/ RENAME es2button@.service) -# copy files to etc, there is a post install script that links default to entrypoint if not already exist -install(FILES resources/default.sh - DESTINATION ${ES2CONF_DIR} - RENAME default - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) -install(FILES resources/README.md DESTINATION ${ES2CONF_DIR} RENAME README.md) -# copy example folder to share -install(DIRECTORY example DESTINATION share/es2button/) - -set(CPACK_GENERATOR DEB) -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Jan Rüth") -set(CPACK_PACKAGE_CONTACT "es2button@djiehmail.com") -set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") -set(CPACK_OUTPUT_FILE_PREFIX "./artifacts") -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS "YES") -# we'll run a script after installation to link default to entrypoint if required -set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/resources/preinst;${CMAKE_CURRENT_SOURCE_DIR}/resources/postinst;") -# since we dynamically load libes2command.so -# let's make sure the deb file depends on the corresponding package -# we also want udev and systemd -set(CPACK_DEBIAN_PACKAGE_DEPENDS "epsonscan2, udev, systemd") -include(CPack) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6efe50c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,779 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "bindgen" +version = "0.69.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bit-set" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e1e6fb1c9e3d6fcdec57216a74eaa03e41f52a22f13a16438251d8e88b89da" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading 0.7.4", +] + +[[package]] +name = "clap" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "es2button" +version = "0.1.0" +dependencies = [ + "clap", + "es2command", + "libusb", + "nix", + "serde", + "serde_json", + "signal-hook", + "thiserror", +] + +[[package]] +name = "es2command" +version = "0.0.1" +dependencies = [ + "es2command-sys", + "foreign-types", + "libc", + "libloading 0.8.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "es2command-sys" +version = "0.0.1" +dependencies = [ + "bindgen", + "cc", + "regex", + "serde", + "serde_repr", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "libusb" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f990ddd929cbe53de4ecd6cf26e1f4e0c5b9796e4c629d9046570b03738aa53" +dependencies = [ + "bit-set", + "libc", + "libusb-sys", +] + +[[package]] +name = "libusb-sys" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c53b6582563d64ad3e692f54ef95239c3ea8069e82c9eb70ca948869a7ad767" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfeae074e687625746172d639330f1de242a178bf3189b51e35a7a21573513ac" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7fef688 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +members = [ + "es2button", + "es2command-sys", + "es2command", +] + +default-members = [ + "es2command-sys", + "es2command", +] + +resolver = "2" \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2685622 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ + +.PHONY: fmt +fmt: + cargo fmt --all --check + +.PHONY: lint +lint: + cargo clippy --workspace --all-targets + +.PHONY: test +test: + cargo test --all-targets + +.PHONY: build +build: + cargo build --all-targets + +.PHONY: deb +deb: + cargo deb -p es2button \ No newline at end of file diff --git a/es2button/Cargo.toml b/es2button/Cargo.toml new file mode 100644 index 0000000..8ef5aa0 --- /dev/null +++ b/es2button/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "es2button" +version = "0.1.0" +authors = ["Jan Rüth "] +edition = "2021" +license = "MIT" +description = "Use buttons on epsonscan-supported scanners" +publish = false + +[dependencies] +clap = { version = "4.4", features = ["derive"] } +es2command = { path = "../es2command" } +libusb = "0.3" +nix = { version = "0.27", features = ["signal"] } +signal-hook = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +thiserror = "1.0" + +[package.metadata.deb] +maintainer = "Jan Rüth " +copyright = "2023, Jan Rüth " +license-file = ["../LICENSE.txt", "2"] +extended-description = """\ +Use buttons on epson scanners \ +""" +depends = "epsonscan2, udev, systemd" +section = "utility" +priority = "optional" +maintainer-scripts = "../resources" +assets = [ + ["../target/release/es2button", "usr/bin/", "755"], + ["../resources/udev-es2button.rules", "lib/udev/rules.d/61-es2button.rules", "755"], + ["../resources/systemd.service", "lib/systemd/system/es2button@.service", "755"], + ["../resources/default.sh", "etc/es2button/default", "775"], + ["../resources/README.md", "etc/es2button/", "644"], + ["../example/*", "share/es2button/", "644"], +] diff --git a/es2button/src/list.rs b/es2button/src/list.rs new file mode 100644 index 0000000..c9e27bc --- /dev/null +++ b/es2button/src/list.rs @@ -0,0 +1,40 @@ +use std::time::Duration; + +use crate::types::{self, UsbDevice, UsbIdentifier}; + +const EPSON_USB_VID: u16 = 0x04b8; + +pub(crate) fn epson_scanners() -> Vec { + let mut devices = Vec::::new(); + + let ctx = libusb::Context::new().unwrap(); + for device in ctx.devices().unwrap().iter() { + let descriptor = device.device_descriptor().unwrap(); + + if descriptor.vendor_id() != EPSON_USB_VID { + continue; + } + let mut handle = device.open().unwrap(); + handle.reset().unwrap(); + + let langs = handle.read_languages(Duration::from_secs(1)).unwrap(); + if langs.is_empty() { + continue; + } + + let name = handle + .read_product_string(langs[0], &descriptor, Duration::from_secs(1)) + .unwrap(); + let vid = descriptor.vendor_id(); + let pid = descriptor.product_id(); + let bus = device.bus_number(); + let dev = device.address(); + + devices.push(UsbDevice { + identifier: UsbIdentifier { name, bus, dev }, + vid, + pid, + }) + } + devices +} diff --git a/es2button/src/listener.rs b/es2button/src/listener.rs new file mode 100644 index 0000000..6e3bd40 --- /dev/null +++ b/es2button/src/listener.rs @@ -0,0 +1,186 @@ +use std::{ + io::{self, Write}, + path::PathBuf, + process::Command, +}; + +use es2command::{ESError, ScannerRef, UsbConnectInfo}; +use nix::unistd::getpid; +use signal_hook::consts::{SIGINT, SIGPIPE}; + +use crate::types::UsbDevice; + +pub struct Listener<'a> { + program: PathBuf, + device: UsbDevice, + scanner: &'a ScannerRef, +} + +impl<'a> Listener<'a> { + pub fn new(device: UsbDevice, program: PathBuf, scanner: &'a ScannerRef) -> Self { + Self { + program, + device, + scanner, + } + } +} + +pub(crate) fn run_listener(device: UsbDevice, program: PathBuf) { + let scanner = es2command::Scanner::default(); + + let connect_info = serde_json::to_string(&UsbConnectInfo::from(device.clone())).unwrap(); + println!("Connecting:\n{}", &connect_info); + scanner.set_connection(&connect_info).unwrap(); + + scanner.set_delegate(Listener::new(device, program, &scanner)); + + scanner.open().unwrap(); + + // wait until we're told to close + + let mut signals = signal_hook::iterator::Signals::new([SIGINT, SIGPIPE]).unwrap(); + + 'outer: loop { + for signal in signals.wait() { + match signal { + SIGINT => { + println!("Got SIGINT terminating"); + break 'outer; + } + SIGPIPE => { + println!("Got SIGPIPE, scanner is gone, terminating"); + break 'outer; + } + num => { + println!("Got unknown signal {}, ignoring it", num); + } + } + } + } + + scanner.close().unwrap(); +} + +impl<'a> Listener<'a> { + fn is_document_loaded(&self) -> Result { + self.scanner + .get_bool_value_for_key(es2command::ESKEY_DOCUMENT_LOADED) + } + fn is_card_scanning(&self) -> Result { + self.scanner + .get_bool_value_for_key(es2command::ESKEY_CARD_SCANNING) + } + + fn handle_button_press(&self, button: u8) -> Result<(), ESError> { + println!("Button pressed: {}", button); + + let doc_present = self.is_document_loaded()?; + let card_scanning = self.is_card_scanning()?; + + self.scanner.close()?; + + let output = Command::new(&self.program) + .env_clear() + .env("ES2_BUTTON_NUM", format!("{}", button)) + .env("ES2_DOC_PRESENT", b2str(doc_present)) + .env("ES2_CARD_SCANNING", b2str(card_scanning)) + .env( + "ES2_DEV", + format!( + "{}:{:03}:{:03}", + self.device.identifier.name, + self.device.identifier.bus, + self.device.identifier.dev + ), + ) + .env("ES2_DEV_VID", format!("{:03}", self.device.vid)) + .env("ES2_DEV_PID", format!("{:03}", self.device.pid)) + .output() + .expect("failed executing program"); + + println!("Script status: {}", output.status); + println!("Script stdout:"); + io::stdout().write_all(&output.stdout).unwrap(); + println!("Script stderr:"); + io::stdout().write_all(&output.stderr).unwrap(); + println!("Resuming from script"); + + self.scanner.open() + } +} + +impl<'a> es2command::ScanDelegate for Listener<'a> { + fn did_encounter_device_communication_error( + &self, + _scanner: &es2command::ScannerRef, + error: es2command::ESError, + ) { + println!("Communication error: {}", error); + println!("Stopping"); + // wakeup listener + nix::sys::signal::kill(getpid(), nix::sys::signal::SIGPIPE).unwrap(); + } + + fn did_press_button(&self, button: u8) { + if let Err(err) = self.handle_button_press(button) { + println!("failed handling button press: {}", err); + } + } + + fn will_begin_continous_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn did_end_continuous_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn will_cancel_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn did_cancel_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn did_complete_scanning_with_error( + &self, + _scanner: &es2command::ScannerRef, + _error: es2command::ESError, + ) { + } + + fn did_interrupt_scanning_with_error( + &self, + _scanner: &es2command::ScannerRef, + _error: es2command::ESError, + ) { + } + + fn will_warm_up(&self, _scanner: &es2command::ScannerRef) {} + + fn did_warm_up(&self, _scanner: &es2command::ScannerRef) {} + + fn network_did_request_start_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn network_did_request_stop_scanning(&self, _scanner: &es2command::ScannerRef) {} + + fn did_disconnect(&self, _scanner: &es2command::ScannerRef) {} + + fn network_did_receive_server_error(&self, _scanner: &es2command::ScannerRef) {} + + fn network_should_prevent_timeout(&self, _scanner: &es2command::ScannerRef) -> bool { + false + } + + fn network_did_timeout(&self, _scanner: &es2command::ScannerRef) {} + + fn is_reserved_by_host(&self, _scanner: &es2command::ScannerRef, _host: String) {} + + fn network_did_request_stop(&self, _scanner: &es2command::ScannerRef) {} + + fn network_did_request_push_scan_connection(&self, _scanner: &es2command::ScannerRef) {} + + fn network_did_notify_status_change(&self, _scanner: &es2command::ScannerRef) {} +} + +fn b2str(b: bool) -> &'static str { + if b { + "Yes" + } else { + "No" + } +} diff --git a/es2button/src/main.rs b/es2button/src/main.rs new file mode 100644 index 0000000..bfa470b --- /dev/null +++ b/es2button/src/main.rs @@ -0,0 +1,61 @@ +mod list; +mod listener; +mod types; +use std::path::PathBuf; + +use clap::Parser; +use types::UsbIdentifier; + +/// Simple program to greet a person +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// The scanner device + #[arg(short, long)] + device: Option, + + /// List scanner devices + #[arg(short, long)] + list: bool, + + #[clap(index = 1)] + pub program: Option, +} + +fn main() { + let args = Args::parse(); + + let mut available_devices = list::epson_scanners(); + + if args.list { + for device in available_devices { + println!( + "{}:{:03}:{:03}", + &device.identifier.name, device.identifier.bus, device.identifier.dev + ); + } + return; + } + + if available_devices.is_empty() { + println!("No devices found"); + return; + } + + let target_device = if let Some(device) = args.device { + let identifier = UsbIdentifier::try_from(device.as_str()).expect("invalid device"); + available_devices + .into_iter() + .find(|x| x.identifier == identifier) + .expect("device not found") + } else { + available_devices.reverse(); + available_devices.pop().unwrap() + }; + + listener::run_listener( + target_device, + args.program + .unwrap_or(PathBuf::from("/etc/es2button/entrypoint")), + ) +} diff --git a/es2button/src/types.rs b/es2button/src/types.rs new file mode 100644 index 0000000..24483d6 --- /dev/null +++ b/es2button/src/types.rs @@ -0,0 +1,67 @@ +use std::num::ParseIntError; + +use es2command::{ConnectionSettings, ESConnectionType, TypeInt, UsbConnectInfo}; +use thiserror::Error; + +#[derive(Debug, PartialEq, Clone)] +pub struct UsbDevice { + pub identifier: UsbIdentifier, + pub vid: u16, + pub pid: u16, +} + +impl From for UsbConnectInfo { + fn from(value: UsbDevice) -> Self { + Self { + connection_setting: vec![ConnectionSettings { + connect_type: TypeInt::Int(ESConnectionType::kESConnectionLocal), + vid: TypeInt::Int(value.vid), + pid: TypeInt::Int(value.pid), + bus_number: TypeInt::Int(value.identifier.bus), + device_number: TypeInt::Int(value.identifier.dev), + }], + } + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct UsbIdentifier { + pub name: String, + pub bus: u8, + pub dev: u8, +} + +#[derive(Debug, Error)] +pub enum ParsingError { + #[error("invalid device identifier, need dev_name:bus:dev got: '{0}'")] + Identifier(String), + #[error("invalid bus, expected integer: '{0}'")] + Bus(ParseIntError), + #[error("invalid dev, expected integer: '{0}'")] + Dev(ParseIntError), +} + +impl TryFrom<&str> for UsbIdentifier { + type Error = ParsingError; + + fn try_from(value: &str) -> Result { + let (name, rest) = value + .split_once(':') + .ok_or(ParsingError::Identifier(value.into()))?; + let (bus, rest) = rest + .split_once(':') + .ok_or(ParsingError::Identifier(value.into()))?; + let (dev, _) = rest + .split_once(':') + .ok_or(ParsingError::Identifier(value.into()))?; + + let bus = bus.parse().map_err(ParsingError::Bus)?; + let dev = dev.parse().map_err(ParsingError::Dev)?; + + Ok(Self { + name: name.to_owned(), + bus, + dev, + }) + } +} diff --git a/es2command-sys/Cargo.toml b/es2command-sys/Cargo.toml new file mode 100644 index 0000000..5e569f7 --- /dev/null +++ b/es2command-sys/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "es2command-sys" +version = "0.0.1" +authors = ["Jan Rüth "] +edition = "2021" +license = "MIT" +description = "Use buttons on epsonscan-supported scanners" +publish = false + +[dependencies] +serde = "1.0" +serde_repr = "0.1" + +[build-dependencies] +bindgen = { version = "0.69" } +cc = "1.0" +regex = "1.10" \ No newline at end of file diff --git a/es2command-sys/build.rs b/es2command-sys/build.rs new file mode 100644 index 0000000..ea3d207 --- /dev/null +++ b/es2command-sys/build.rs @@ -0,0 +1,89 @@ +use std::{env, fs, path::PathBuf}; + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let install_lib_dir = format!( + r#""/usr/lib/{}-{}-{}""#, + env::var("CARGO_CFG_TARGET_ARCH").unwrap(), + env::var("CARGO_CFG_TARGET_OS").unwrap(), + env::var("CARGO_CFG_TARGET_ENV").unwrap() + ); + + let mut builder = cc::Build::new(); + builder + .file("cinterface/src/delegate.cpp") + .file("cinterface/src/scanner.cpp") + .file("cinterface/src/wrapper.cpp") + .define("INSTALL_LIB_DIR", install_lib_dir.as_str()) + .include("cinterface/include") + .flag("-Wno-unused-parameter") + .flag("-Wno-unused-variable") + .flag("-Wno-missing-field-initializers") + .static_flag(true) + .cpp(true) + .std("c++11") + .pic(true); + + #[cfg(debug_assertions)] + builder.debug(true); + + builder.compile("es2commandwrapper"); + + println!("cargo:rerun-if-changed=cinterface/src/delegate.cpp"); + println!("cargo:rerun-if-changed=cinterface/src/internal.hpp"); + println!("cargo:rerun-if-changed=cinterface/src/scanner.cpp"); + println!("cargo:rerun-if-changed=cinterface/src/wrapper.cpp"); + + println!( + "cargo:rustc-link-search=native={}", + out_dir.to_str().unwrap() + ); + println!("cargo:rustc-link-lib=static=es2commandwrapper"); + + let bindings = bindgen::Builder::default() + .clang_args([ + "-Icinterface/include", + "-x", + "c++", + "-std=c++11", + &format!("-DINSTALL_LIB_DIR={}", install_lib_dir.as_str()), + ]) + .use_core() + .ctypes_prefix("::core::ffi") + .header("cinterface/include/wrapper.hpp") + .allowlist_file("cinterface/include/wrapper.hpp") + .allowlist_file("cinterface/include/ES2Command/ES2CommandAPI.h") + .blocklist_function("ESCreateScanner") + .allowlist_file("cinterface/include/ES2Command/ESCommandProperties.h") + .allowlist_file("cinterface/include/ES2Command/ESPropertyKeys.h") + .allowlist_file("cinterface/include/common.hpp") + .allowlist_file("cinterface/include/delegate.hpp") + .allowlist_file("cinterface/include/scanner.hpp") + .rustified_enum("ES.*") + .emit_builtins() + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .formatter(bindgen::Formatter::Rustfmt) + .generate() + .unwrap(); + + // we'll derive Serialize_repr for the enums + let mut output = b"use serde_repr::*;\n".to_vec(); + + bindings + .write(Box::new(&mut output)) + .expect("failed generating bindings"); + + let re = regex::Regex::new(r"#\[derive\((.*)\)\]\npub enum").unwrap(); + + let bindings = re + .replace_all( + std::str::from_utf8(&output[..]).unwrap(), + "#[derive(Serialize_repr, Deserialize_repr, $1)]\npub enum", + ) + .to_string(); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(out_dir); + fs::write(out_path.join("bindings.rs"), bindings).expect("Couldn't write bindings!"); +} diff --git a/es2command-sys/cinterface/include/ES2Command/ES2CommandAPI.h b/es2command-sys/cinterface/include/ES2Command/ES2CommandAPI.h new file mode 100644 index 0000000..f112066 --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/ES2CommandAPI.h @@ -0,0 +1,56 @@ +// This file is copied from epsonscan2 6.7.43.0-1 +// The original file is licensed as LGPL 2.1 +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! +//! @file ES2CommandAPI.h +//! +//! @brif スキャナー操作インターフェースの定義 +//! DLL アプリケーション用にエクスポートされる関数を定義します。 +//! @note +//! @versoin 1.0 +//! @par Copyright SEIKO EPSON Corporation +//! @par 更新履歴 +//! @par - 新規作成 2014/12/25 +//! +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +/////////////////////////////////////////////////////////////////// +// +// DLL設定の定義 +// +/////////////////////////////////////////////////////////////////// +#define _UNICODE_ESSCANNER // Unicode版 + +#if defined(ES2COMMAND_EXPORTS) +#define ESSCANNER_API __declspec(dllexport) +#elif defined(ES2COMMAND_EXPORTS) +#define ESSCANNER_API __declspec(dllimport) +#else +#define ESSCANNER_API +#endif + +#include "ESCommandProperties.h" +#include "IESScanner.h" + +extern "C" { + +// [ ESCreateScanner ] +// +// スキャナ操作インターフェースの作成 +// +// @param +// eCommandType : スキャナのコマンドタイプ +// ppScanner : +// 作成されたスキャナーインターフェースを受け取るポインタへのポインタ +// @return +// エラーコード +// 成功 : kESErrorNoError +// 失敗 : その他 +ESSCANNER_API ESErrorCode ESCreateScanner(ESCommandType eCommandType, + IESScanner** ppScanner); +}; + +typedef ESErrorCode (*PFN_CREATE_SCANNER)(ESCommandType eCommandType, + IESScanner** ppScanner); diff --git a/es2command-sys/cinterface/include/ES2Command/ESCommandProperties.h b/es2command-sys/cinterface/include/ES2Command/ESCommandProperties.h new file mode 100644 index 0000000..dda7b53 --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/ESCommandProperties.h @@ -0,0 +1,397 @@ +// This file is copied from epsonscan2 6.7.43.0-1 +// The imports have been modified to make them standalone +// The rest of the file is untouched +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! +//! @file ES2CommandProperties.h +//! +//! @brif ES2Command 外部公開コマンドの定義 +//! @note +//! @versoin 1.0 +//! @par Copyright SEIKO EPSON Corporation +//! @par 更新履歴 +//! @par - 新規作成 2014/12/25 +//! +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "types.h" + +// エラーコード +typedef enum { + kESErrorNoError = 0, // 成功 + kESErrorFatalError = 1, // 失敗 + kESErrorInvalidParameter = 2, // パラメーター異常 + + // Driver internal error + kESErrorMemoryError = 100, // メモリーエラー + kESErrorSequenceError = 101, // シーケンスエラー + kESErrorFileWriteError = 102, + kESErrorFileReadError = 103, + kESErrorScanAreaTooLargeError = 104, + + // Communication error + kESErrorDataSendFailure = 200, // データー転送エラー + kESErrorDataReceiveFailure = 201, // データー受信エラー + kESErrorInvalidResponse = 202, // 不正なレスポンス + kESErrorDeviceOpenError = 203, + + // Device error + kESErrorDeviceInUse = 300, + kESErrorDeviceInBusy = 301, + kESErrorPaperEmpty = 302, + kESErrorPaperJam = 303, + kESErrorPaperDoubleFeed = 304, + kESErrorCoverOpen = 305, + kESErrorTrayClose = 307, + kESErrorCRLock = 308, + kESErrorLampError = 309, + kESErrorLampTime = 310, + kESErrorAuthFailure = 311, + kESErrorNoPermission = 312, + kESErrorLowBattery = 313, + kESErrorFocusError = 314, + kESErrorDeviceFatalError = 315, + kESErrorCRSheetSensorError = 316, + kESErrorPaperProtect = 317, + kESErrorGAPSensorError = 318, + kESErrorPaperDoubleFeed2 = 319, + kESErrorPoseError = 320, + kESErrorSeparationLeverError = 321, + kESErrorETSensorError = 322, + kESErrorADFLiftError = 323, + kESErrorUserAuthEnabled = 324, + kESErrorPrintStackerError = 325, + kESErrorPaperRemoveError = 326, + kESErrorSkewDetectError = 327, +} ESErrorCode; + +typedef enum { + kESErrorStatusNoError = kESErrorNoError, + kESErrorStatusFatalError = kESErrorFatalError, + kESErrorStatusDeviceInBusy = kESErrorDeviceInBusy, + kESErrorStatusPaperEmpty = kESErrorPaperEmpty, + kESErrorStatusPaperJam = kESErrorPaperJam, + kESErrorStatusPaperDoubleFeed = kESErrorPaperDoubleFeed, + kESErrorStatusCoverOpen = kESErrorCoverOpen, + kESErrorStatusTrayClose = kESErrorTrayClose, + kESErrorStatusCRLock = kESErrorCRLock, + kESErrorStatusLampError = kESErrorLampError, + kESErrorStatusLampTime = kESErrorLampTime, + kESErrorStatusAuthFailure = kESErrorAuthFailure, + kESErrorStatusNoPermission = kESErrorNoPermission, + kESErrorStatusLowBattery = kESErrorLowBattery, + kESErrorStatusCRSheetSensorError = kESErrorCRSheetSensorError, + kESErrorStatusPaperProtect = kESErrorPaperProtect, + kESErrorStatusGAPSensorError = kESErrorGAPSensorError, + kESErrorStatusPoseError = kESErrorPoseError, + kESErrorStatusSeparationLeverError = kESErrorSeparationLeverError, + kESErrorStatusETSensorError = kESErrorETSensorError, + kESErrorStatusADFLiftError = kESErrorADFLiftError, + kESErrorStatusPrintStackerError = kESErrorPrintStackerError, + kESErrorStatusPaperRemoveError = kESErrorPaperRemoveError, + kESErrorStatusSkewDetectError = kESErrorSkewDetectError +} ESErrorStatus; + +typedef enum { + kESScannerPositionStatusFlat = 0, + kESScannerPositionStatusTilt = 1, + kESScannerPositionStatusInvalid = 2, +} ESScannerPositionStatus; + +typedef enum { + kESDocumentSeparationStatusOff = 0, + kESDocumentSeparationStatusOn = 1, + kESDocumentSeparationStatusSoft = 2, +} ESDocumentSeparationStatus; + +typedef enum { + kESBatteryStatusNone = 0, + kESBatteryStatusLow = 1, +} ESBatteryStatus; + +typedef enum { + kESSensorGlassNone = 0, + kESSensorGlassDirty = 1, +} ESSensorGlassStatus; + +typedef enum { + kESWarningNone = 0, + kESWarningNeedCleaning = 1, +} ESWarningStatus; + +typedef enum { + kESUnavailableScanParameterStatusAll = 0, + kESUnavailableScanParameterStatusAFMC = 1, + kESUnavailableScanParameterStatusPCS = 2, +} ESUnavailableScanParameterStatus; + +// スキャナーのコマンドタイプ +typedef enum { + kESCommandTypeESCI = 0, + kESCommandTypeESCI2 = 1, +} ESCommandType; + +// 給紙設定 +typedef enum { + kESFunctionalUnitUnknown = 0, + kESFunctionalUnitFlatbed = 1, + kESFunctionalUnitDocumentFeeder = 2, + kESFunctionalUnitTransparent = 3, + kESFunctionalUnitTPUAreaGuide = 6, +} ESFunctionalUnitType; + +// カラーフォーマット +typedef enum { + kESColorFormatMonoDropR1 = 0x0101, + kESColorFormatMonoDropG1 = 0x0201, + kESColorFormatMonoDropB1 = 0x0401, + kESColorFormatMono1 = 0x0801, + kESColorFormatMonoDropR8 = 0x0108, + kESColorFormatMonoDropG8 = 0x0208, + kESColorFormatMonoDropB8 = 0x0408, + kESColorFormatMono8 = 0x0808, + kESColorFormatMonoDropR16 = 0x0110, + kESColorFormatMonoDropG16 = 0x0210, + kESColorFormatMonoDropB16 = 0x0410, + kESColorFormatMono16 = 0x0810, + kESColorFormatRGB3 = 0x0701, + kESColorFormatRGB24 = 0x0708, + kESColorFormatRGB48 = 0x0710, +} ESColorFormat; + +typedef enum { + kESColorFormatMaskBitDepth = 0x00FF, + kESColorFormatMaskChannel = 0xFF00, + kESColorFormatMaskRChannel = 0x0100, + kESColorFormatMaskGChannel = 0x0200, + kESColorFormatMaskBChannel = 0x0400, + kESColorFormatMaskMChannel = 0x0800, + kESColorFormatMaskRGBChannel = 0x0700, +} ESColorFormatMask; + +enum { + kESHalftoneNone = 0x01, + kESHalftoneA = 0x00, + kESHalftoneB = 0x10, + kESHalftoneC = 0x20, + kESHalftoneTET = 0x03, + kESHalftoneDitherA = 0x80, + kESHalftoneDitherB = 0x90, + kESHalftoneDitherC = 0xA0, + kESHalftoneDitherD = 0xB0, + kESHalftoneUserDefinedDitherA = 0xC0, + kESHalftoneUserDefinedDitherB = 0xD0, +}; +typedef UInt8 ESHalftone; + +// 画像データーの圧縮タイプ +typedef enum { + kESImageFormatRaw = 0, + kESImageFormatJPEG = 1, +} ESImageFormat; + +// ガンマモード +enum { + kESGammaMode10 = 0x03, + kESGammaMode18 = 0x04, + kESGammaMode22 = 0x22, +}; +typedef UInt8 ESGammaMode; + +enum { + kESGammaChannelMaster = 'M', + kESGammaChannelRed = 'R', + kESGammaChannelGreen = 'G', + kESGammaChannelBlue = 'B', +}; +typedef UInt8 ESGammaChannel; + +enum { + kESScanningModeNormal = 0x00, + kESScanningModeHighSpeed = 0x01, +}; +typedef UInt8 ESScanningMode; + +// 静音モード +enum { + kESQuietModePreferDeviceSetting = 0x00, + kESQuietModeOff = 0x01, + kESQuietModeOn = 0x02, +}; +typedef UInt8 ESQuietMode; + +enum { + kESLaminatedPaperModeOff = 0, + kESLaminatedPaperModeOn = 1, +}; +typedef UInt8 ESLaminatedPaperMode; + +// カラーマトリックス +typedef enum { + kESColorMatrixUnit = 0, + kESColorMatrix8 = 1, + kESColorMatrix16 = 2, +} ESColorMatrixMode; + +enum { + kESDuplexType1Pass = 1, + kESDuplexType2Pass = 2, +}; +typedef UInt8 ESDuplexType; + +typedef enum { + kESLampModeDefault = 0x00, + kESLampModeUseLamp1 = 0x01, + kESLampModeUseLamp2 = 0x02, +} ESLampMode; + +enum { + kESDoubleFeedDetectionDisable = 0x00, + kESDoubleFeedDetectionLow = 0x01, + kESDoubleFeedDetectionHigh = 0x02, + kESDoubleFeedDetectionVeryLow = 0x03, +}; +typedef UInt8 ESDoubleFeedDetection; + +enum { + kESFocusDefault = 0x40, + kESFocusAuto = 0xFF, +}; +typedef UInt8 ESFocus; + +typedef enum { + kESEdgeFillColorWhite = 0, + kESEdgeFillColorBlack = 1, +} ESEdgeFillColor; + +// Digital ICE設定 +typedef enum { + kESDigitalICEDisable = 0, + kESDigitalICEEnable = 1, + kESDigitalICELiteEnable = 2, +} ESDigitalICE; + +typedef enum { + kESGuidePositionLeft = 0, + kESGuidePositionCenter = 1, + kESGuidePositionRight = 2, +} ESGuidePosition; + +enum { + kESFilmTypePositive = 0, + kESFilmTypeNegative = 1, +}; +typedef UInt8 ESFilmType; + +enum { + kESJobModeNone = 0, + kESJobModeStandard = 1, + kESJobModeContinue = 2, + kESJobModeAFM = 3, + kESJobModeAFMC = 4, +}; +typedef UInt8 ESJobMode; + +enum { + kESSensorGlassDirtSensitivityOff = 0, + kESSensorGlassDirtSensitivityLow = 1, + kESSensorGlassDirtSensitivityNormal = 2, +}; +typedef UInt8 ESSensorGlassDirtSensitivity; + +enum { + kESBGColorWhite = 0, + kESBGColorBlack = 1, + kESBGColorGray = 2, +}; +typedef UInt8 ESBGColor; + +enum { kESClientApplicationES2 = 0, kESClientApplicationESS = 1 }; +typedef UInt8 ESClientApplication; + +enum { + kESBackgroundRemovalLevelOff = 0, + kESBackgroundRemovalLevelLow = 1, + kESBackgroundRemovalLevelHigh = 2, +}; +typedef UInt8 ENUM_ES_BACKGROUNDREMOVAL_LEVEL; + +enum { + kESSharpnessFilterLevelSmoothingHigh = 8, + kESSharpnessFilterLevelSmoothingMiddle = 7, + kESSharpnessFilterLevelSmoothingLow = 6, + kESSharpnessFilterLevelSmoothingVeryLow = 5, + kESSharpnessFilterLevelNorm = 0, + kESSharpnessFilterLevelSharpVeryLow = 1, + kESSharpnessFilterLevelSharpLow = 2, + kESSharpnessFilterLevelSharpMiddle = 3, + kESSharpnessFilterLevelSharpHigh = 4, +}; +typedef UInt8 ENUM_ES_SHARPNESSFILTER_LEVEL; + +enum { + kESDefaultPasswordTypeSerial = 0, // 製品シリアル番号 + kESDefaultPasswordTypeUnique = 1, // ユニークな番号(製品本体に添付) +}; +typedef UInt8 ENUM_ES_DEFAULTPASSWORD_TYPE; + +enum { + kESDirectPowerOn_Off = 0, + kESDirectPowerOn_On = 1, +}; +typedef UInt8 ENUM_ES_DIRECTPOWERON_MODE; +enum { + kESNonConnectPowerOff_Off = 0, + kESNonConnectPowerOff_On = 1, +}; +typedef UInt8 ENUM_ES_NONCONNECTPOWEROFF_MODE; +enum { + kESADFPaperProtection_Off = 0, + kESADFPaperProtection_Low = 1, + kESADFPaperProtection_Normal = 2, + kESADFPaperProtection_High = 3, +}; +typedef UInt8 ENUM_ES_ADFPAPERPROTECTION_MODE; +enum { + kESBehaviorWhenDoubleFeed_Immediately = 0, + kESBehaviorWhenDoubleFeed_StopAfterEjecting = 1, +}; +typedef UInt8 ENUM_ES_BEHAVIORWHENDOUBLEFEED_MODE; + +enum { + kESCleaningWarningNotify_Off = 0, + kESCleaningWarningNotify_On = 1, +}; +typedef UInt8 ENUM_ES_CLEANINGWARNINGNOTIFY_MODE; + +// スキャナとの接続タイプ +typedef enum { + kESConnectionLocal = 0, // ローカル接続(USB) + kESConnectionNetworkIS = 1, // ネットワーク接続( ISプロトコル ) + kESConnectionNetworkNT = 2, // ネットワーク接続( NTプロトコル ) + kESConnectionInterpreter = 3, +} ESConnectionType; + +enum { + kESColorCounterTypePref = 0, // 最終画像は本体のカラータイプと同一 + kESColorCounterTypeColor = 1, // 最終画像はカラー + kESColorCounterTypeMono = 2, // 最終画像はモノクロ(グレー/2値) +}; +typedef UInt8 ENUM_ES_COLORCOUNTER_TYPE; + +STATIC_CONST_KEY ES_CNCT_KEY_ROOT = ES_STRING("ConnectionSetting"); +STATIC_CONST_KEY ES_CNCT_KEY_TYPE = ES_STRING("ConnectType"); +STATIC_CONST_KEY ES_CNCT_KEY_INTERNALNAME = ES_STRING("InternalName"); +STATIC_CONST_KEY ES_CNCT_KEY_VID = ES_STRING("VID"); +STATIC_CONST_KEY ES_CNCT_KEY_PID = ES_STRING("PID"); +STATIC_CONST_KEY ES_CNCT_KEY_BUS_NUMBER = ES_STRING("BUS_NUMBER"); +STATIC_CONST_KEY ES_CNCT_KEY_DEVICE_NUMBER = ES_STRING("DEVICE_NUMBER"); + +STATIC_CONST_KEY ES_CNCT_KEY_ADDRESS = ES_STRING("Address"); +STATIC_CONST_KEY ES_CNCT_KEY_CONNECTION_TIMEOUT = + ES_STRING("ConnectionTimeout"); +STATIC_CONST_KEY ES_CNCT_KEY_COMMUNICATION_TIMEOUT = + ES_STRING("CommunicationTimeout"); +STATIC_CONST_KEY ES_CNCT_KEY_INTERPRETER_NAME = ES_STRING("InterpreterName"); diff --git a/es2command-sys/cinterface/include/ES2Command/ESPropertyKeys.h b/es2command-sys/cinterface/include/ES2Command/ESPropertyKeys.h new file mode 100644 index 0000000..3a82814 --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/ESPropertyKeys.h @@ -0,0 +1,884 @@ +// This file is copied from epsonscan2 6.7.43.0-1 +// The imports have been modified to make them standalone +// The original file is licensed as LGPL 2.1 +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! +//! @file ESPropertyKeys.h +//! +//! @brif ES2Command 外部公開キーの定義 +//! @note +//! @versoin 1.0 +//! @par Copyright SEIKO EPSON Corporation +//! @par 更新履歴 +//! @par - 新規作成 2014/12/25 +//! +//////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "types.h" + +// +// プロパティキー +// + +// +// ※ Value : +// すべてのキーにおいて、コマンドが対応するキーだがスキャナー設定により現在サポートされない値の場合 +// nullptrを返す +// + +STATIC_CONST_KEY kESVersion = + ES_STRING("version"); // Value : [r] ESString + // AllValues : ESString + // AvailableValues : + +STATIC_CONST_KEY kESWorkFolder = + ES_STRING("workFolder"); // Value : [rw] ESString + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESInterruptionEnabled = ES_STRING( + "interruptionEnabled"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESErrorStatus = + ES_STRING("errorStatus"); // Value : [r] ESNumber (ESErrorCode) + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESBatteryStatus = + ES_STRING("batteryStatus"); // Value : [r] ESNumber + // (ESBatteryStatus) AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESSensorGlassStatus = + ES_STRING("sensorGlassStatus"); // Value : [r] ESNumber + // (ESSensorGlassStatus) AllValues : + // nullptr AvailableValues : + +STATIC_CONST_KEY kESScannerPositionStatus = ES_STRING( + "scannerPositionStatus"); // Value : [r] ESNumber + // (ENUM_ES_SCANNER_POSITION_STATUS) AllValues : + // nullptr AvailableValues : + +STATIC_CONST_KEY kESWarningStatus = + ES_STRING("warningStatus"); // Value : [r] ESNumber + // (ENUM_ES_WARNING_STATUS) AllValues : + // nullptr AvailableValues : + +STATIC_CONST_KEY kESUnavailableScanParameterStatus = ES_STRING( + "unavailableScanParameterStatus"); // Value : [r] ESNumber + // (ENUM_ES_UNAVAILABLE_SCAN_PARAMETER_STATUS) + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESAuthentication = + ES_STRING("authentication"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false + // ) AvailableValues : + +STATIC_CONST_KEY kESAuthenticationEnabled = + ES_STRING("authenticationEnabled"); // Value : [rw] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + +STATIC_CONST_KEY kESLengthPadding = + ES_STRING("lengthPadding"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false + // ) AvailableValues : + +STATIC_CONST_KEY kESAutoFeedingMode = + ES_STRING("autoFeedingMode"); // Value : [r] bool + // AllValues : ESIndexSet ( true, + // false ) AvailableValues : + +STATIC_CONST_KEY kESContinuousAutoFeedingMode = + ES_STRING("continuousAutoFeedingMode"); // Value : [r] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + +STATIC_CONST_KEY kESAutoFeedingModeTimeout = ES_STRING( + "autoFeedingModeTimeout"); // Value : [rw] ESNumber (minutes) + // AllValues : ST_ES_RANGE + // AvailableValues : ST_ES_RANGE + +STATIC_CONST_KEY kESProductName = + ES_STRING("productName"); // Value : [r] ESString + // AllValues : ESString + // AvailableValues : + +STATIC_CONST_KEY kESSerialNumber = + ES_STRING("serialNumber"); // Value : [r] ESString + // AllValues : ESString + // AvailableValues : + +STATIC_CONST_KEY kESAuthUsername = + ES_STRING("authUsername"); // Value : [rw] ESString + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESAuthPassword = + ES_STRING("authPassword"); // Value : [rw] ESString + // AllValues : nullptr + +STATIC_CONST_KEY kESDefaultPasswordType = + ES_STRING("defaultPasswordType"); // Value : [r] ESNumber + // (ENUM_ES_DEFAULTPASSWORD_TYPE) + // AllValues : nullptr AvailableValues : + +STATIC_CONST_KEY kESAdminLock = + ES_STRING("adminLock"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESAdminLockEnabled = ES_STRING( + "adminLockEnabled"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESAdminLockPassword = + ES_STRING("adminLockPassword"); // Value : [rw] ESString + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESFunctionalUnitType = ES_STRING( + "functionalUnitType"); // Value : [rw] ESNumber + // (ESFunctionalUnitType) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESXResolution = + ES_STRING("xResolution"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESYResolution = + ES_STRING("yResolution"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESOpticalResolution = + ES_STRING("opticalResolution"); // Value : [r] ESNumber + // AllValues : ESNumber + // AvailableValues : ESNumber + +STATIC_CONST_KEY kESMaxScanSize = + ES_STRING("maxScanSize"); // Value : [r] ST_ES_SIZE_F + // AllValues : ST_ES_SIZE_F + // AvailableValues : + +STATIC_CONST_KEY kESScanArea = + ES_STRING("scanArea"); // Value : [rw] ST_ES_RECT_F + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESScanAreaInPixel = + ES_STRING("scanAreaInPixel"); // Value : [rw] ST_ES_RECT_UN32 + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESScanSize = + ES_STRING("scanSize"); // Value : [rw] ST_ES_SIZE_F + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESScanSizeInPixel = + ES_STRING("scanSizeInPixel"); // Value : [rw] ST_ES_SIZE_UN32 + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESXOffsetMargin = + ES_STRING("xOffsetMargin"); // Value : [rw] ESFloat + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESYOffsetMargin = + ES_STRING("yOffsetMargin"); // Value : [rw] ESFloat + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESColorFormat = + ES_STRING("colorFormat"); // Value : [rw] ESNumber + // (ESColorFormat) AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESColorCounterType = + ES_STRING("colorCounterType"); // Value : [rw] ESNumber + // (ENUM_ES_COLORCOUNTER_TYPE) + +STATIC_CONST_KEY kESBitsPerPixel = + ES_STRING("bitsPerPixel"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESHalftone = + ES_STRING("halftone"); // Value : [rw] ESNumber (ESHalftone) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESGammaMode = + ES_STRING("gammaMode"); // Value : [rw] ESNumber (ESGammaMode) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESGammaTableMono = + ES_STRING("gammaTableMono"); // Value : [rw] ESIndexArray(256 + // array) or nullptr(get only) +STATIC_CONST_KEY kESGammaTableRed = + ES_STRING("gammaTableRed"); // Value : [rw] ESIndexArray(256 + // array) or nullptr(get only) +STATIC_CONST_KEY kESGammaTableGreen = + ES_STRING("gammaTableGreen"); // Value : [rw] ESIndexArray(256 + // array) or nullptr(get only) +STATIC_CONST_KEY kESGammaTableBlue = + ES_STRING("gammaTableBlue"); // Value : [rw] ESIndexArray(256 + // array) or nullptr(get only) AllValues : + // nullptr AvailableValues : nullptr + +STATIC_CONST_KEY kESColorMatrix = + ES_STRING("colorMatrix"); // Value : [rw] ESFloatArray(3 x 3 + // Floats) or nullptr(get only) AllValues : + // nullptr AvailableValues : nullptr + +STATIC_CONST_KEY kESThreshold = + ES_STRING("threshold"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESQuietMode = + ES_STRING("quietMode"); // Value : [rw] ESNumber (ESQuietMode) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESBufferSize = + ES_STRING("bufferSize"); // Value : [rw] ESNumber + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESDuplexType = + ES_STRING("duplexType"); // Value : [r] ESNumber (ESDuplexType) + // AllValues : ESNumber + // AvailableValues : + +STATIC_CONST_KEY kESDuplex = + ES_STRING("duplex"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESDoubleFeedDetection = ES_STRING( + "doubleFeedDetection"); // Value : [rw] ESNumber + // (ESDoubleFeedDetection) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESMinDoubleFeedDetectionRangeLength = ES_STRING( + "minDoubleFeedDetectionRangeLength"); // Value : [r] ESFloat (inches) + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESDoubleFeedDetectionRangeOffset = ES_STRING( + "doubleFeedDetectionRangeOffset"); // Value : [rw] ESFloat (inches) + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESDoubleFeedDetectionRangeLength = ES_STRING( + "doubleFeedDetectionRangeLength"); // Value : [rw] ESFloat (inches) + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESLenghtDoubleFeedDetection = + ES_STRING("lengthDoubleFeedDetection"); // Value : [rw] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + // ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESLengthDoubleFeedDetectionLength = ES_STRING( + "lengthDoubleFeedDetectionLength"); // Value : [rw] ESFloat (inches) + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESImageDoubleFeedDetection = + ES_STRING("imageDoubleFeedDetection"); // Value : [rw] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + // ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESImagePaperProtection = ES_STRING( + "imagePaperProtection"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESCarrierSheetDetection = + ES_STRING("carrierSheetDeteciton"); // Value : [r] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + +STATIC_CONST_KEY kESAutoCropping = + ES_STRING("autoCropping"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESAutoCroppingInscribed = ES_STRING( + "autoCroppingInscribed"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESCroppableResolutions = ES_STRING( + "croppableResolutions"); // Value : [r] ESIndexSet or ST_ES_RANGE + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : + +STATIC_CONST_KEY kESCroppingSize = ES_STRING( + "croppingSize"); // Value : [rw] ESFloat + // AllValues : ESFloatArray or ST_ES_RANGE_F + // AvailableValues : ESFloatArray or ST_ES_RANGE_F + +STATIC_CONST_KEY kESPagesToBeScanned = + ES_STRING("pagesToBeScanned"); // Value : [rw] ESNumber + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESDocumentLoaded = + ES_STRING("documentLoaded"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false + // ) AvailableValues : + +STATIC_CONST_KEY kESDocumentSeparation = + ES_STRING("documentSeparation"); // Value : [r] bool + // AllValues : ESIndexSet ( true, + // false ) AvailableValues : + +STATIC_CONST_KEY kESCardScanning = + ES_STRING("cardScanning"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : + +STATIC_CONST_KEY kESCleaning = + ES_STRING("cleaning"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : + +STATIC_CONST_KEY kESCalibration = + ES_STRING("calibration"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : + +STATIC_CONST_KEY kESDetectedDocumentSize = + ES_STRING("detectedDocumentSize"); // Value : [r] ST_ES_SIZE_F +STATIC_CONST_KEY kESEdgeFillWidthRight = + ES_STRING("edgeFillWidthRight"); // Value : [rw] ESFloat +STATIC_CONST_KEY kESEdgeFillWidthTop = + ES_STRING("edgeFillWidthTop"); // Value : [rw] ESFloat +STATIC_CONST_KEY kESEdgeFillWidthLeft = + ES_STRING("edgeFillWidthLeft"); // Value : [rw] ESFloat +STATIC_CONST_KEY kESEdgeFillWidthBottom = ES_STRING( + "edgeFillWidthBottom"); // Value : [rw] ESFloat + // AllValues : ESFloatArray or ST_ES_RANGE_F + // AvailableValues : ESFloatArray or ST_ES_RANGE_F + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESEdgeFillColor = + ES_STRING("edgeFillColor"); // Value : [rw] ESNumber + // (ESEdgeFillColor) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESDigitalICE = + ES_STRING("digitalICE"); // Value : [rw] ESNumber (ESDigitalICE) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESFilmType = + ES_STRING("filmType"); // Value : [rw] ESNumber (ESFilmType) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESScanningMode = + ES_STRING("scanningMode"); // Value : [rw] ESNumber + // (ESScanningMode) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESLaminatedPaperMode = ES_STRING( + "laminatedPaperMode"); // Value : [rw] ESNumber + // (ESLaminatedPaperMode) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESBGColor = + ES_STRING("BGColor"); // Value : [rw] ESNumber + // (ENUM_ES_BG_COLOR) AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESWarmingUp = + ES_STRING("warmingUp"); // Value : [r] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : + +STATIC_CONST_KEY kESButtonStatus = + ES_STRING("buttonStatus"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESLampMode = + ES_STRING("lampMode"); // Value : [rw] ESNumber (ESLampMode) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESPowerSaveTime = + ES_STRING("powerSaveTime"); // Value : [rw] ESNumber + // (ENUM_ESCI_POWER_SAVE_TIME) AllValues : + // ESIndexSet or ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESMaxFocus = + ES_STRING("maxFocus"); // Value : [r] ESFloat (mm) + // AllValues : ESFloat + // AvailableValues : + +STATIC_CONST_KEY kESMinFocus = + ES_STRING("minFocus"); // Value : [r] ESFloat (mm) + // AllValues : ESFloat + // AvailableValues : + +STATIC_CONST_KEY kESFocus = + ES_STRING("focus"); // Value : [rw] ESFloat (mm) + // AllValues : nullptr + // AvailableValues : nullptr + +STATIC_CONST_KEY kESSimplexScanCounter = + ES_STRING("simplexScanCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE or nullptr AvailableValues + // : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESDuplexScanCounter = + ES_STRING("duplexScanCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE or nullptr AvailableValues + // : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESSimplexCardScanCounter = ES_STRING( + "simplexCardScanCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // or nullptr AvailableValues : ESIndexSet or + // ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESDuplexCardScanCounter = ES_STRING( + "duplexCardScanCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // or nullptr AvailableValues : ESIndexSet or + // ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESLamp1Counter = + ES_STRING("lamp1Counter"); // Value : [rw] ESNumber +STATIC_CONST_KEY kESLamp2Counter = ES_STRING( + "lamp2Counter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE or nullptr + // AvailableValues : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESPickupRollerCounter = + ES_STRING("pickupRollerCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE or nullptr AvailableValues + // : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESSeparationPadCounter = ES_STRING( + "separationPadCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE or + // nullptr AvailableValues : ESIndexSet or + // ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESRetardRollerCounter = + ES_STRING("retardRollerCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE or nullptr AvailableValues + // : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESScanCounter = ES_STRING( + "scanCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE or nullptr + // AvailableValues : ESIndexSet or ST_ES_RANGE or nullptr + +STATIC_CONST_KEY kESCaptureCommandSupported = + ES_STRING("captureCommandSupported"); // Value : [rw] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + // ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESShouldIgnoreCancelFromScanner = ES_STRING( + "shouldIgnoreCancelFromScanner"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, + // false ) AvailableValues : ESIndexSet + // ( true, false ) + +STATIC_CONST_KEY kESGuidePosition = + ES_STRING("guidePosition"); // Value : [r] ESNumber + // (ESGuidePosition) AllValues : + // ESIndexSet AvailableValues : + +STATIC_CONST_KEY kESGuidePositionFB = + ES_STRING("guidePositionFB"); // Value : [rw] ESNumber + // (ESGuidePosition) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESGuidePositionADF = + ES_STRING("guidePositionADF"); // Value : [rw] ESNumber + // (ESGuidePosition) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESGuidelessADF = + ES_STRING("guidelessADF"); // Value : [r] bool + +STATIC_CONST_KEY kESDisableJobContinue = ES_STRING( + "disableJobContinue"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESDisableKeepingCapture = ES_STRING( + "disableKeepingCapture"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESMaxImagePixels = + ES_STRING("maxImagePixels"); // Value : [r] ST_ES_SIZE_F + // AllValues : ST_ES_SIZE_F + // AvailableValues : + +STATIC_CONST_KEY kESMaxScanSizeInLongLength = ES_STRING( + "maxScanSizeInLongLength"); // Value : [ESCI: rw, ESCI/2: r] + // ST_ES_SIZE_F AllValues : ST_ES_SIZE_F + // AvailableValues : nullptr + +STATIC_CONST_KEY kESMaxLongLengthTable = + ES_STRING("maxLongLengthTable"); // Value : [r] ESDictionary + // AllValues : ESDicArray + // AvailableValues : nullptr + +STATIC_CONST_KEY kESMinScanSize = + ES_STRING("minScanSize"); // Value : [r] ST_ES_SIZE_F + // AllValues : ST_ES_SIZE_F + // AvailableValues : + +STATIC_CONST_KEY kESImageFormat = + ES_STRING("imageFormat"); // Value : [rw] ESNumber + // (ESImageFormat) AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESColorMatrixMode = + ES_STRING("colorMatrixMode"); // Value : [rw] ESNumber + // (ESColorMatrixMode) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESSkewCorrection = + ES_STRING("skewCorrection"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false + // ) AvailableValues : ESIndexSe + +STATIC_CONST_KEY kESJPEGQuality = + ES_STRING("JPEGQuality"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPaperEndDetection = ES_STRING( + "paperEndDetection"); // Value : [rw] bool + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESOverScan = + ES_STRING("overScan"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESOverScanForCropping = ES_STRING( + "overScanForCropping"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESPassportCarrierSheetScan = + ES_STRING("passportCarrierSheetScan"); // Value : [rw] bool + // AllValues : ESIndexSet ( + // true, false ) AvailableValues : + // ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESPowerOffTime = + ES_STRING("powerOffTime"); // Value : [rw] ESNumber(min) +STATIC_CONST_KEY kESPowerOffTime2nd = ES_STRING( + "powerOffTime2nd"); // Value : [rw] ESNumber(min) + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESFirstPCConnectionDate = ES_STRING( + "firstPCConnectionDate"); // Value : [r] ESString ("%Y-%m-%d + // %H:%M" in UTC) AllValues : ESIndexSet + // or ST_ES_RANGE AvailableValues + +STATIC_CONST_KEY kESDocumentFeederLamp1Counter = ES_STRING( + "documentFeederLamp1Counter"); // Value : [rw] ESNumber +STATIC_CONST_KEY kESDocumentFeederLamp2Counter = ES_STRING( + "documentFeederLamp2Counter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : ESIndexSet + // or ST_ES_RANGE + +STATIC_CONST_KEY kESPaperJamCounter = ES_STRING( + "paperJamCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESUltraSonicDoubleFeedCounter = ES_STRING( + "ultraSonicDoubleFeedCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESLengthDoubleFeedCounter = ES_STRING( + "lengthDoubleFeedCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESRollerKitCounter = ES_STRING( + "rollerKitCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESImageDoubleFeedCounter = ES_STRING( + "imageDoubleFeedCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPaperProtectionCounter = ES_STRING( + "paperProtectionCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPaperProtectionOverflowCounter = ES_STRING( + "paperProtectionOverflowCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPaperProtectionDistortionCounter = ES_STRING( + "paperProtectionDistortionCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESSpecialDocumentCounter = ES_STRING( + "specialDocumentCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPassportCarrierSheetCounter = ES_STRING( + "passportCarrierSheetCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESFlatbedLamp1Counter = + ES_STRING("flatbedLamp1Counter"); // Value : [rw] ESNumber +STATIC_CONST_KEY kESFlatbedLamp2Counter = ES_STRING( + "flatbedLamp2Counter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESDocumentTopCorrectionFront = ES_STRING( + "documentTopCorrectionFront"); // Value : [rw] ESFloat (1/1000 + // inch) AllValues : ESFloatArray or + // ST_ES_RANGE_F AvailableValues : + // ESFloatArray or ST_ES_RANGE_F + +STATIC_CONST_KEY kESDocumentTopCorrectionBack = ES_STRING( + "documentTopCorrectionBack"); // Value : [rw] ESFloat (1/1000 + // inch) AllValues : ESFloatArray or + // ST_ES_RANGE_F AvailableValues : + // ESFloatArray or ST_ES_RANGE_F + +STATIC_CONST_KEY kESDocumentDriveCorrectionFront = ES_STRING( + "documentDriveCorrectionFront"); // Value : [rw] ESFloat %単位 + // AllValues : ESFloatArray or + // ST_ES_RANGE_F AvailableValues : + // ESFloatArray or ST_ES_RANGE_F + +STATIC_CONST_KEY kESDocumentDriveCorrectionBack = ES_STRING( + "documentDriveCorrectionBack"); // Value : [rw] ESFloat %単位 + // AllValues : ESFloatArray or + // ST_ES_RANGE_F AvailableValues : + // ESFloatArray or ST_ES_RANGE_F + +STATIC_CONST_KEY kESLightIntensityBack = ES_STRING( + "lightIntensityBack"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESLightIntensityFB = ES_STRING( + "lightIntensityFB"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESDocumentFeederBGLevelFront = ES_STRING( + "documentFeederBGLevelFront"); // Value : [r] ESDictionary + // (BGLevel Dictionary) AllValues : + // nullptr AvailableValues : + +STATIC_CONST_KEY kESDocumentFeederBGLevelBack = ES_STRING( + "documentFeederBGLevelBack"); // Value : [r] ESDictionary + // (BGLevel Dictionary) AllValues : + // nullptr AvailableValues : + +STATIC_CONST_KEY kESPickupRollerLifeLimit = + ES_STRING("pickupRollerLifeLimit"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESSeparationPadLifeLimit = + ES_STRING("separationPadLifeLimit"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESRollerKitLifeLimit = + ES_STRING("rollerKitLifeLimit"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESRetardRollerLifeLimit = + ES_STRING("retardRollerLifeLimit"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESPickupRollerNearend = + ES_STRING("pickupRollerNearend"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESSeparationPadNearend = + ES_STRING("separationPadNearend"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESRetardRollerNearend = + ES_STRING("retardRollerNearend"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESRollerKitNearend = + ES_STRING("rollerKitNearend"); // Value : [r] ESNumber + // AllValues : nullptr + // AvailableValues : + +STATIC_CONST_KEY kESSensorGlassDirtSensitivity = ES_STRING( + "sensorGlassDirtSensitivity"); // Value : [rw] ESNumber + // (ESSensorGlassDirtSensitivity) AllValues + // : ESIndexSet AvailableValues : + // ESIndexSet + +STATIC_CONST_KEY kESClientApplication = + ES_STRING("clientApplication"); // Value : [rw] ESNumber + // (ESClientApplication) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESDirectPowerOn = + ES_STRING("directPowerOn"); // Value : [rw] ESNumber + // (ENUM_ES_DIRECTPOWERON_MODE) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESNonConnectPowerOff = ES_STRING( + "nonConnectPowerOff"); // Value : [rw] ESNumber + // (ENUM_ES_NONCONNECTPOWEROFF_MODE) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESADFPaperProtection = ES_STRING( + "adfPaperProtection"); // Value : [rw] ESNumber + // (ENUM_ES_ADFPAPERPROTECTION_MODE) AllValues : + // ESIndexSet AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESBehaviorWhenDoubleFeed = ES_STRING( + "behaviorWhenDoubleFeed"); // Value : [rw] ESNumber + // (ENUM_ES_BEHAVIORWHENDOUBLEFEED_MODE) + // AllValues : ESIndexSet + // AvailableValues : ESIndexSet + +STATIC_CONST_KEY kESCleaningWarningNotifyCount = ES_STRING( + "cleaningWarningNotifyCount"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : ESIndexSet + // or ST_ES_RANGE + +STATIC_CONST_KEY kESRollerKitNotifyCount = ES_STRING( + "rollerKitNotifyCount"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESRetardRollerNotifyCount = ES_STRING( + "retardRollerNotifyCount"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESSeparationPadNotifyCount = + ES_STRING("separationPadNotifyCount"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or + // ST_ES_RANGE AvailableValues : + // ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESPickupRollerNotifyCount = ES_STRING( + "pickupRollerNotifyCount"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESCleaningWarningCounter = ES_STRING( + "cleaningWarningCounter"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESCleaningWarningNotify = ES_STRING( + "cleaningWarningNotify"); // Value : [rw] ESNumber + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESDetectColorTypeEnabled = ES_STRING( + "detectColorTypeEnabled"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESDetectBlankPageEnabled = ES_STRING( + "detectBlankPageEnabled"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +STATIC_CONST_KEY kESDetectBlankPageLevel = ES_STRING( + "detectBlankPageLevel"); // Value : Integer + // AllValues : ESIndexSet or ST_ES_RANGE + // AvailableValues : ESIndexSet or ST_ES_RANGE + +STATIC_CONST_KEY kESSkipImageEnhancement = ES_STRING( + "skipImageEnhancement"); // Value : [rw] bool + // AllValues : ESIndexSet ( true, false ) + // AvailableValues : ESIndexSet ( true, false ) + +// +// kESDocumentFeederBGLevelFront, +// kESDocumentFeederBGLevelBackで取得される辞書内のキー。 +// +STATIC_CONST_KEY kESBGLevelKeyRed = ES_STRING("bgLevelKeyRed"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyRedWidth = + ES_STRING("bgLevelKeyRedWidth"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyGreen = + ES_STRING("bgLevelKeyGreen"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyGreenWidth = + ES_STRING("bgLevelKeyGreenWidth"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyBlue = ES_STRING("bgLevelKeyBlue"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyBlueWidth = + ES_STRING("bgLevelKeyBlueWidth"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyMono = ES_STRING("bgLevelKeyMono"); // r ESNumber +STATIC_CONST_KEY kESBGLevelKeyMonoWidth = + ES_STRING("bgLevelKeyMonoWidth"); // r ESNumber + +// Image processing Keys +STATIC_CONST_KEY kESBackgroundRemoval = ES_STRING( + "backgroundRemoval"); // rw ESNumber (ENUM_ES_BACKGROUNDREMOVAL_LEVEL) +STATIC_CONST_KEY kESBrightness = + ES_STRING("brightness"); // rw ESNumber [-100 ~ 100] +STATIC_CONST_KEY kESContrast = + ES_STRING("contrast"); // rw ESNumber [-100 ~ 100] +STATIC_CONST_KEY kESGammaScale = + ES_STRING("gammaScale"); // rw ESNumber [5 ~ 30] +STATIC_CONST_KEY kESSharpnessFilter = ES_STRING( + "sharpnessFilterLevel"); // rw ESNumber (ENUM_ES_SHARPNESSFILTER_LEVEL) +STATIC_CONST_KEY kESADFLoadSupported = ES_STRING("adfLoadSupported"); \ No newline at end of file diff --git a/es2command-sys/cinterface/include/ES2Command/ESResultString.h b/es2command-sys/cinterface/include/ES2Command/ESResultString.h new file mode 100644 index 0000000..d546c27 --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/ESResultString.h @@ -0,0 +1,54 @@ +// This file is copied from epsonscan2 6.7.43.0-1 +// The imports have been modified to make them standalone +// The classes are untouched + +#pragma once + +#include + +#include "types.h" + +//----------------------------------------=----------------------------------------�� +/*!@brief ������ۑ��p�C���^�[�t�F�[�X + */ +class IESResultString { + public: + virtual ~IESResultString() {} + + //----------------------------------------=----------------------------------------�� + /*!@brief �������setter + @param[in] pszString ������ + @return + ������ۑ��ɐ��������ꍇtrue��Ԃ��A���s�����ꍇfalse��Ԃ��B + */ + virtual bool Set(const ES_CHAR *pszString) = 0; + + //----------------------------------------=----------------------------------------�� + /*!@brief �������getter + @return ������ւ̃|�C���^��Ԃ��B + */ + virtual const ES_CHAR *Get() = 0; +}; + +class CESResultString : public IESResultString { + public: + CESResultString() { m_String.clear(); } + + virtual ~CESResultString() { m_String.clear(); } + + virtual bool Set(const ES_CHAR *pszString) { + if (!pszString) { + return false; + } + try { + m_String = pszString; + } catch (const std::bad_alloc &) { + _ASSERT(FALSE); + return false; + } + return true; + } + virtual const ES_CHAR *Get() { return m_String.c_str(); } + + ESString m_String; +}; diff --git a/es2command-sys/cinterface/include/ES2Command/IESScanner.h b/es2command-sys/cinterface/include/ES2Command/IESScanner.h new file mode 100644 index 0000000..88881db --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/IESScanner.h @@ -0,0 +1,483 @@ +// This file is copied from epsonscan2 6.7.43.0-1 +// The imports have been modified to make them standalone +// The actual interfaces remain untouched +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! +//! @file IESScanner.h +//! +//! @brif スキャナ操作インターフェース クラス +//! @note +//! @versoin 1.0 +//! @par Copyright SEIKO EPSON Corporation +//! @par 更新履歴 +//! @par - 新規作成 2014/12/25 +//! +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define CALLBACK + +#include "ESCommandProperties.h" +#include "ESResultString.h" +#include "types.h" + +class IESScanner; +class IESScannedImage; +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// [ IESScannerDelegate ] +// +// @brif スキャン結果を受け取る Delegate クラスのインターフェース +// DLL利用側で、IESScannerにセットする。 +// +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +class IESScannerDelegate { + public: + /** + 連続する一連のスキャンの開始を通知する。 + 連続するスキャンは、ADFでの間断ないスキャンを指す。 + */ + virtual void CALLBACK + ScannerWillBeginContinuousScanning(IESScanner* pScanner) = 0; + + /** + 連続する一連のスキャンの終了を通知する。 + 連続するスキャンは、ADFでの間断ないスキャンを指す。 + */ + virtual void CALLBACK + ScannerDidEndContinuousScanning(IESScanner* pScanenr) = 0; + + /** + 1ページ分のスキャン開始を通知する。 + */ + virtual void CALLBACK ScannerWillScanToScannedImage( + IESScanner* pScanner, IESScannedImage* pESImage) = 0; + + /** + 1ページ分のスキャン終了を通知する。 + */ + virtual void CALLBACK ScannerDidScanToScannedImage( + IESScanner* pScanner, IESScannedImage* pESImage) = 0; + + /** + スキャンのキャンセルが行われることを通知する。 + */ + virtual void CALLBACK ScannerWillCancelScanning(IESScanner* pScanner) = 0; + + /** + スキャンのキャンセルを通知する。 + */ + virtual void CALLBACK ScannerDidCancelScanning(IESScanner* pScanner) = 0; + + /** + スキャンの完了を通知する。 + AFM有効時はAFMの終了時のみ発行され、それ以外では発行されない。 + */ + virtual void CALLBACK ScannerDidCompleteScanningWithError( + IESScanner* pScanner, ESErrorCode err) = 0; + + /** + エラーによるスキャンの中断を通知する。 + */ + virtual void CALLBACK ScannerDidInterruptScanningWithError( + IESScanner* pcScanner, ESErrorCode err) = 0; + + /** + 通信エラーを通知する。 + */ + virtual void CALLBACK ScannerDidEncounterDeviceCommunicationError( + IESScanner* pScanner, ESErrorCode err) = 0; + + /** + ウォームアップ開始を通知する。 + */ + virtual void CALLBACK ScannerWillWarmUp(IESScanner* pScanner) = 0; + + /** + ウォームアップ終了を通知する。 + */ + virtual void CALLBACK ScannerDidWarmUp(IESScanner* pScanner) = 0; + + virtual void CALLBACK + NetworkScannerDidRequestStartScanning(IESScanner* pScanner) = 0; + + virtual void CALLBACK + NetworkScannerDidRequestStopScanning(IESScanner* pScanner) = 0; + + virtual void CALLBACK ScannerDidDisconnect(IESScanner* pScanner) = 0; + + virtual void CALLBACK + NetworkScannerDidReceiveServerError(IESScanner* pScanner) = 0; + + virtual BOOL CALLBACK + NetworkScannerShouldPreventTimeout(IESScanner* pScanner) = 0; + + virtual void CALLBACK NetworkScannerDidTimeout(IESScanner* pScanner) = 0; + + /** + ネットワークスキャナーが別のクライアントによって使用されていることを通知する。 + */ + virtual void CALLBACK ScannerIsReservedByHost(IESScanner* pScanner, + const ES_CHAR* pszAddress) = 0; + + /** + スキャナーのプッシュスキャンボタンが押されたことを通知する。 + */ + virtual void CALLBACK ScannerDidPressButton(UInt8 un8ButtonNumber) = 0; + /** + スキャナーのストップボタンが押されたことを通知する。 + */ + virtual void CALLBACK ScannerDidRequestStop(IESScanner* pScanner) = 0; + + /** + スキャナーがプッシュスキャン(ジョブ情報)を要求したことを通知する。 + */ + virtual void CALLBACK + ScannerDidRequestPushScanConnection(IESScanner* pScanner) = 0; + + /** + スキャナーの状態(姿勢・分離レバー)が変化したことを通知する。 + */ + virtual void CALLBACK ScannerDidNotifyStatusChange(IESScanner* pScanner) = 0; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// [ IESScanner ] +// +// @brif スキャナ操作インターフェースクラス +// +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +class IESScanner { + public: + //============================================================================================== + // + // 初期化・終了処理 + // + //============================================================================================== + + // + // スキャン時のプロセス処理を行うDelegateを設定する + // + virtual void SetDelegate(IESScannerDelegate* pDelegate) = 0; + + // + // スキャナとの接続設定を行う + // 設定値は下記のJSONフォーマット文字列を渡す + // + // 【 ローカル接続 kESConnectionLocal 】 + // + // { + // "ConnectionSetting" : [ + // { + // "ConnectType" :{ + // "int" : 0, + // }, + // "InternalName" : { + // "string" : "デバイス名(DeviceInternalName)" + // } + // } + // ] + // } + // + // 【 ネットワーク接続 kESConnectionNetworkIS | kESConnectionNetworkNT 】 + // + // { + // "ConnectionSetting" : [ + // { + // "ConnectType" :{ + // "int" : 1 // ISプロトコルの場合 + // } + // "Address" : { + // "string" : "IPアドレス" または"ホスト名" + // } + // "ConnectionTimeout" : { // 接続タイムアウト時間(秒)[オプション] + // "int" : 30 + // } + // "CommunicationTimeout" : { // + // 通信タイムアウト時間(秒)[オプション] + // "int" : 30 + // } + // } + // ] + // } + // + // + virtual ESErrorCode SetConnection(ES_JSON_CPTR pszJSON) = 0; + + // + // クラスインスタンスを破壊します。 + // + virtual void DestroyInstance() = 0; + + //============================================================================================== + // + // オープン・クローズ + // + //============================================================================================== + + // + // スキャナとの通信を開始する。 + // + virtual ESErrorCode Open() = 0; + + // + // スキャナとの通信を終了する + // + virtual ESErrorCode Close() = 0; + + // + // スキャナがオープンしているか? + // + virtual bool IsOpened() const = 0; + + //============================================================================================== + // + // スキャン操作 + // + //============================================================================================== + + // + // 現在のスキャン設定でスキャンを開始する。 + // + virtual ESErrorCode Scan() = 0; + + // + // 別スレッドでスキャンを開始する。 + // + virtual ESErrorCode ScanInBackground() = 0; + + // + // スキャン処理をキャンセルする。 + // キャンセル成功時には、DidCompleteScanningWithErrorにて通知される + // + virtual ESErrorCode Cancel() = 0; + + // + // + // + virtual ESErrorCode Abort() = 0; + + // + // スキャン中か? + // + virtual bool IsScanning() const = 0; + + //============================================================================================== + // + // メンテナンス操作 + // + //============================================================================================== + + // + // スキャナセンサーのクリーニング動作を要求する。 + // + virtual ESErrorCode DoCleaning() = 0; + + // + // スキャナセンサーのキャリブレーションを要求する。 + // + virtual ESErrorCode DoCalibration() = 0; + + //============================================================================================== + // + // AutoFeedingMode操作 + // + //============================================================================================== + + // + // 中断中か? + // + virtual bool IsInterrupted() const = 0; + + // + // AFM中か? + // + virtual bool IsAfmEnabled() const = 0; + + // + // Auto Feeding Mode タイムアウトチェック開始 + // + virtual ESErrorCode ScheduleAutoFeedingModeTimeout() = 0; + + //============================================================================================== + // + // ジョブリクエスト + // + //============================================================================================== + + // + // スキャンジョブの開始 + // + virtual ESErrorCode StartJobInMode(ESJobMode eJobMode) = 0; + + // + // スキャンジョブの終了 + // + virtual ESErrorCode StopJobInMode(ESJobMode eJobMode) = 0; + + //============================================================================================== + // + // その他 + // + //============================================================================================== + + // + // オートフォーカスを要求する。 + // @param pfOutFocus + // オートフォーカスの結果として焦点位置を受け取るバッファへのポインタ。単位はmm。 + // @return エラーコード。 + // + virtual ESErrorCode DoAutoFocus(ESFloat* pfOutFocus) = 0; + + // + // スキャナーパネルのプッシュスキャン可能状態を設定する + // + virtual ESErrorCode SetPanelToPushScanReady(BOOL bPushScanReady) = 0; + + virtual BOOL IsScannableDeviceConfig() = 0; + + // + // パスワード + // + virtual ESErrorCode UnlockAdministratorLock() = 0; + virtual ESErrorCode LockAdministratorLock() = 0; + + //============================================================================================== + // + // スキャナ情報 + // + //============================================================================================== + + // + // 設定をリセットする + // + virtual ESErrorCode Reset() = 0; + + // + // すべての設定可能なキーを取得する + // + // @param + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // 取得した文字列は呼び出し側でESDeleteJSON()を利用して削除すること + // + // { + // AllKeys : { + // "array_str" : [ + // "< key name1 >" , + // "< key name2 >" , + // ] + // } + // } + // + virtual ESErrorCode GetAllKeys(IESResultString* pstrResult) = 0; + + // + // 指定したキーのデフォルト値を取得する + // + // @param + // pszKey : キー名 + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // { + // "< key name >" : 値データ ※別資料参照 + // } + // + virtual ESErrorCode GetDefaultValueForKey(ES_CHAR_CPTR pszKey, + IESResultString* pstrResult) = 0; + + // + // 指定したキーの設定値を取得する + // + // @param + // pszKey : キー名 + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // { + // "< key name >" : 値データ ※別資料参照 + // } + // + virtual ESErrorCode GetValueForKey(ES_CHAR_CPTR pszKey, + IESResultString* pstrResult) = 0; + + // + // 指定したキーに値を設定する + // + // @param + // pszKey : キー名 + // ppszJSON : 設定値を記述したJSON文字列ポインタ + // + // { + // "< key name >" : 値データ ※別資料参照 + // } + // + virtual ESErrorCode SetValueForKey(ES_CHAR_CPTR pszKey, + ES_JSON_CPTR pszJSON) = 0; + + // + // JSONでまとめて値を設定する + // + // { + // "< key name1 >" : 値データ ※別資料参照 + // "< key name2 >" : 値データ ※別資料参照 + // ... + // } + // + virtual ESErrorCode SetValuesWithJSON(ES_JSON_CPTR pszJSON) = 0; + + // + // 指定したキーにセット可能なすべての値を取得する + // + // param + // pszKey : キー名 + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // { + // "< key name >" : 値データ ※別資料参照 + // } + // + virtual ESErrorCode GetAllValuesForKey(ES_CHAR_CPTR pszKey, + IESResultString* pstrResult) = 0; + + // + // 全キーに対する、セット可能なすべての値を取得する + // + // param + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // { + // "< key name1 >" : 値データ ※別資料参照 , + // "< key name2 >" : 値データ ※別資料参照 , + // ... + // } + // + virtual ESErrorCode GetAllValues(IESResultString* pstrResult) = 0; + + // + // 指定したキーにセット可能なすべての値を取得する + // + // param + // pszKey : キー名 + // ppszJSON : 結果のJSON文字列を受け取るポインタ + // + // { + // "< key name >" : 値データ ※別資料参照 + // } + // + virtual ESErrorCode GetAvailableValuesForKey(ES_CHAR_CPTR pszKey, + IESResultString* pstrResult) = 0; + + // + // 全キーに対する、セット可能なすべての値を取得する + // + // { + // "< key name1 >" : 値データ ※別資料参照 , + // "< key name2 >" : 値データ ※別資料参照 , + // ... + // ... + // } + // + virtual ESErrorCode GetAllAvailableValues(IESResultString* pstrResult) = 0; +}; diff --git a/es2command-sys/cinterface/include/ES2Command/LICENSE b/es2command-sys/cinterface/include/ES2Command/LICENSE new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/LICENSE @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/es2command-sys/cinterface/include/ES2Command/types.h b/es2command-sys/cinterface/include/ES2Command/types.h new file mode 100644 index 0000000..42f8cbd --- /dev/null +++ b/es2command-sys/cinterface/include/ES2Command/types.h @@ -0,0 +1,23 @@ +// This file is a mixture of things found in epsonscan2 6.7.43.0-1 +// These types are useful to interface with the es2command API +// The source is licensed as LGPL 2.1 +#pragma once + +#include + +#include + +#define STATIC_CONST_KEY static const char* const +#define ES_STRING(str) str + +#define ESString std::string +#define _ASSERT(x) + +// Types use in interfaces +typedef char ES_CHAR; +typedef const ES_CHAR* ES_CHAR_CPTR; +typedef ES_CHAR* ES_JSON_PTR; +typedef ES_CHAR_CPTR ES_JSON_CPTR; +typedef uint8_t UInt8; +typedef float ESFloat; +typedef int BOOL; \ No newline at end of file diff --git a/es2command-sys/cinterface/include/common.hpp b/es2command-sys/cinterface/include/common.hpp new file mode 100644 index 0000000..1effa32 --- /dev/null +++ b/es2command-sys/cinterface/include/common.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct delegate; +typedef struct delegate delegate_t; + +struct scanner; +typedef struct scanner scanner_t; + +#ifdef __cplusplus +} +#endif diff --git a/es2command-sys/cinterface/include/delegate.hpp b/es2command-sys/cinterface/include/delegate.hpp new file mode 100644 index 0000000..ebd9057 --- /dev/null +++ b/es2command-sys/cinterface/include/delegate.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "ES2Command/ESCommandProperties.h" +#include "common.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*delegate_cb)(void*, scanner_t*); +typedef bool (*delegate_cb_ret_bool)(void*, scanner_t*); +typedef void (*delegate_cb_with_error_code)(void*, scanner_t*, ESErrorCode); +typedef void (*delegate_cb_with_cstr)(void*, scanner_t*, const char*); +typedef void (*delegate_cb_with_button)(void*, uint8_t); + +delegate_t* delegate_new( + void* ctx, + delegate_cb_with_error_code did_encounter_device_communication_error_cb, + delegate_cb_with_button did_press_button_cb, + delegate_cb will_begin_continous_scanning_cb, + delegate_cb did_end_continuous_scanning_cb, + delegate_cb will_cancel_scanning_cb, delegate_cb did_cancel_scanning_cb, + delegate_cb_with_error_code did_complete_scanning_with_error_cb, + delegate_cb_with_error_code did_interrupt_scanning_with_error_cb, + delegate_cb will_warm_up_cb, delegate_cb did_warm_up_cb, + delegate_cb network_did_request_start_scanning_cb, + delegate_cb network_did_request_stop_scanning_cb, + delegate_cb did_disconnect_cb, + delegate_cb network_did_receive_server_error_cb, + delegate_cb_ret_bool network_should_prevent_timeout_cb, + delegate_cb network_did_timeout_cb, + delegate_cb_with_cstr is_reserved_by_host_cb, + delegate_cb did_request_stop_cb, + delegate_cb did_request_push_scan_connection_cb, + delegate_cb did_notify_status_change_cb); + +void delegate_free(delegate_t* obj); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/es2command-sys/cinterface/include/scanner.hpp b/es2command-sys/cinterface/include/scanner.hpp new file mode 100644 index 0000000..366a44f --- /dev/null +++ b/es2command-sys/cinterface/include/scanner.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include "common.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +bool scanner_eq(scanner_t* a, scanner_t* b); +void scanner_set_delegate(scanner_t* scanner, delegate_t* delegate); +ESErrorCode scanner_set_connection(scanner_t* scanner, const char* json); + +delegate_t* scanner_destroy_instance(scanner_t* scanner); +ESErrorCode scanner_open(scanner_t* scanner); + +ESErrorCode scanner_close(scanner_t* scanner); + +bool scanner_is_opened(scanner_t* scanner); + +ESErrorCode scanner_scan(scanner_t* scanner); + +ESErrorCode scanner_scan_in_background(scanner_t* scanner); + +ESErrorCode scanner_cancel(scanner_t* scanner); +ESErrorCode scanner_abort(scanner_t* scanner); +bool scanner_is_scanning(scanner_t* scanner); +ESErrorCode scanner_do_cleaning(scanner_t* scanner); + +ESErrorCode scanner_do_calibration(scanner_t* scanner); + +bool scanner_is_interrupted(scanner_t* scanner); + +bool scanner_is_afm_enabled(scanner_t* scanner); + +ESErrorCode scanner_schedule_auto_feeding_mode_timeout(scanner_t* scanner); + +ESErrorCode scanner_start_job_in_mode(scanner_t* scanner, uint8_t eJobMode); + +ESErrorCode scanner_stop_job_in_mode(scanner_t* scanner, uint8_t eJobMode); + +ESErrorCode scanner_do_auto_focus(scanner_t* scanner, float* pfOutFocus); + +ESErrorCode scanner_set_panel_to_push_scan_ready(scanner_t* scanner, + bool bPushScanReady); + +bool scanner_is_scannable_device_config(scanner_t* scanner); + +ESErrorCode scanner_unlock_administrator_lock(scanner_t* scanner); + +ESErrorCode scanner_lock_administrator_lock(scanner_t* scanner); + +ESErrorCode scanner_reset(scanner_t* scanner); + +ESErrorCode scanner_get_all_keys(scanner_t* scanner, char** oJSONStr); +ESErrorCode scanner_get_default_value_for_key(scanner_t* scanner, + const char* key, + char** pstrResult); + +ESErrorCode scanner_get_value_for_key(scanner_t* scanner, const char* key, + char** pstrResult); +ESErrorCode scanner_set_value_for_key(scanner_t* scanner, const char* pszKey, + const char* pszJSON); + +ESErrorCode scanner_set_values_with_JSON(scanner_t* scanner, + const char* pszJSON); + +ESErrorCode scanner_get_all_values_for_key(scanner_t* scanner, const char* key, + char** pstrResult); + +ESErrorCode scanner_get_all_values(scanner_t* scanner, char** pstrResult); + +ESErrorCode scanner_get_available_values_for_key(scanner_t* scanner, + const char* key, + char** pstrResult); +ESErrorCode scanner_get_all_available_values(scanner_t* scanner, + char** pstrResult); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/es2command-sys/cinterface/include/wrapper.hpp b/es2command-sys/cinterface/include/wrapper.hpp new file mode 100644 index 0000000..c5706e9 --- /dev/null +++ b/es2command-sys/cinterface/include/wrapper.hpp @@ -0,0 +1,23 @@ +#include "ES2Command/ES2CommandAPI.h" +#include "ES2Command/ESCommandProperties.h" +#include "ES2Command/ESPropertyKeys.h" +#include "common.hpp" +#include "delegate.hpp" +#include "scanner.hpp" + +// INSTALL_LIB_DIR is passed as a cmd line argument from the build script +static const char DEFAULT_INSTALL_LIB_DIR[] = INSTALL_LIB_DIR "/epsonscan2"; +static const char DEFAULT_ES_CREATE_SCANNER_SYMBOL_NAME[] = "ESCreateScanner"; + +#ifdef __cplusplus +extern "C" { +#endif + +ESErrorCode scanner_create(PFN_CREATE_SCANNER fptr, ESCommandType commandType, + scanner_t** ppScanner); + +void scanner_free(scanner_t* scanner); + +#ifdef __cplusplus +} +#endif diff --git a/es2command-sys/cinterface/src/delegate.cpp b/es2command-sys/cinterface/src/delegate.cpp new file mode 100644 index 0000000..34fa955 --- /dev/null +++ b/es2command-sys/cinterface/src/delegate.cpp @@ -0,0 +1,239 @@ +#include "delegate.hpp" + +#include +#include + +#include "ES2Command/ESCommandProperties.h" +#include "common.hpp" +#include "internal.hpp" + +void ScannerDelegate::SetCtx(void* target) { this->_target = target; }; + +void ScannerDelegate::ScannerDidEncounterDeviceCommunicationError( + IESScanner* pScanner, ESErrorCode err) { + if (this->_did_encounter_device_communication_error_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_encounter_device_communication_error_cb(this->_target, &scanner, + err); + } +}; + +void ScannerDelegate::ScannerDidPressButton(UInt8 un8ButtonNumber) { + printf("Button %d pressed in wrapper, dispatching to %p\n", un8ButtonNumber, + this->_did_press_button_cb); + if (this->_did_press_button_cb != NULL) { + this->_did_press_button_cb(this->_target, un8ButtonNumber); + } +}; + +void ScannerDelegate::ScannerWillBeginContinuousScanning(IESScanner* pScanner) { + if (this->_will_begin_continuous_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_will_begin_continuous_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidEndContinuousScanning(IESScanner* pScanner) { + if (this->_did_end_continuous_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_end_continuous_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerWillScanToScannedImage(IESScanner* pScanner, + IESScannedImage* pESImage){ + +}; + +void ScannerDelegate::ScannerDidScanToScannedImage(IESScanner* pScanner, + IESScannedImage* pESImage){}; + +void ScannerDelegate::ScannerWillCancelScanning(IESScanner* pScanner) { + if (this->_will_cancel_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_will_cancel_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidCancelScanning(IESScanner* pScanner) { + if (this->_did_cancel_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_cancel_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidCompleteScanningWithError(IESScanner* pScanner, + ESErrorCode err) { + if (this->_did_complete_scanning_with_error_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_complete_scanning_with_error_cb(this->_target, &scanner, err); + } +}; + +void ScannerDelegate::ScannerDidInterruptScanningWithError(IESScanner* pScanner, + ESErrorCode err) { + if (this->_did_interrupt_scanning_with_error_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_interrupt_scanning_with_error_cb(this->_target, &scanner, err); + } +}; + +void ScannerDelegate::ScannerWillWarmUp(IESScanner* pScanner) { + if (this->_will_warm_up_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_will_warm_up_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidWarmUp(IESScanner* pScanner) { + if (this->_did_warm_up_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_warm_up_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::NetworkScannerDidRequestStartScanning( + IESScanner* pScanner) { + if (this->_network_did_request_start_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_network_did_request_start_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::NetworkScannerDidRequestStopScanning( + IESScanner* pScanner) { + if (this->_network_did_request_stop_scanning_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_network_did_request_stop_scanning_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidDisconnect(IESScanner* pScanner) { + if (this->_did_disconnect_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_disconnect_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::NetworkScannerDidReceiveServerError( + IESScanner* pScanner) { + if (this->_network_did_receive_server_error_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_network_did_receive_server_error_cb(this->_target, &scanner); + } +}; + +BOOL ScannerDelegate::NetworkScannerShouldPreventTimeout(IESScanner* pScanner) { + if (this->_network_should_prevent_timeout_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + return this->_network_should_prevent_timeout_cb(this->_target, &scanner); + } + return false; +}; + +void ScannerDelegate::NetworkScannerDidTimeout(IESScanner* pScanner) { + if (this->_network_did_timeout_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_network_did_timeout_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerIsReservedByHost(IESScanner* pScanner, + const ES_CHAR* pszAddress) { + if (this->_is_reserved_by_host_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_is_reserved_by_host_cb(this->_target, &scanner, pszAddress); + } +}; + +void ScannerDelegate::ScannerDidRequestStop(IESScanner* pScanner) { + if (this->_did_request_stop_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_request_stop_cb(this->_target, &scanner); + } +}; + +void ScannerDelegate::ScannerDidRequestPushScanConnection( + IESScanner* pScanner) { + if (this->_did_request_push_scan_connection_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_request_push_scan_connection_cb(this->_target, &scanner); + } +}; +void ScannerDelegate::ScannerDidNotifyStatusChange(IESScanner* pScanner) { + if (this->_did_notify_status_change_cb != NULL) { + scanner_t scanner; + scanner.obj = pScanner; + this->_did_notify_status_change_cb(this->_target, &scanner); + } +}; + +#ifdef __cplusplus +extern "C" { +#endif + +delegate_t* delegate_new( + void* ctx, + delegate_cb_with_error_code did_encounter_device_communication_error_cb, + delegate_cb_with_button did_press_button_cb, + delegate_cb will_begin_continous_scanning_cb, + delegate_cb did_end_continuous_scanning_cb, + delegate_cb will_cancel_scanning_cb, delegate_cb did_cancel_scanning_cb, + delegate_cb_with_error_code did_complete_scanning_with_error_cb, + delegate_cb_with_error_code did_interrupt_scanning_with_error_cb, + delegate_cb will_warm_up_cb, delegate_cb did_warm_up_cb, + delegate_cb network_did_request_start_scanning_cb, + delegate_cb network_did_request_stop_scanning_cb, + delegate_cb did_disconnect_cb, + delegate_cb network_did_receive_server_error_cb, + delegate_cb_ret_bool network_should_prevent_timeout_cb, + delegate_cb network_did_timeout_cb, + delegate_cb_with_cstr is_reserved_by_host_cb, + delegate_cb did_request_stop_cb, + delegate_cb did_request_push_scan_connection_cb, + delegate_cb did_notify_status_change_cb) { + delegate_t* obj = (delegate_t*)malloc(sizeof(delegate_t)); + obj->ctx = ctx; + obj->obj = new ScannerDelegate(); + obj->obj->Initialize( + did_encounter_device_communication_error_cb, did_press_button_cb, + will_begin_continous_scanning_cb, did_end_continuous_scanning_cb, + will_cancel_scanning_cb, did_cancel_scanning_cb, + did_complete_scanning_with_error_cb, did_interrupt_scanning_with_error_cb, + will_warm_up_cb, did_warm_up_cb, network_did_request_start_scanning_cb, + network_did_request_stop_scanning_cb, did_disconnect_cb, + network_did_receive_server_error_cb, network_should_prevent_timeout_cb, + network_did_timeout_cb, is_reserved_by_host_cb, did_request_stop_cb, + did_request_push_scan_connection_cb, did_notify_status_change_cb); + + obj->obj->SetCtx(ctx); + + return obj; +} + +void delegate_free(delegate_t* obj) { + delete obj->obj; + free(obj); +} + +#ifdef __cplusplus +} +#endif diff --git a/es2command-sys/cinterface/src/internal.hpp b/es2command-sys/cinterface/src/internal.hpp new file mode 100644 index 0000000..ae3839a --- /dev/null +++ b/es2command-sys/cinterface/src/internal.hpp @@ -0,0 +1,125 @@ +#pragma once + +#include "ES2Command/IESScanner.h" +#include "delegate.hpp" + +struct scanner { + IESScanner* obj; + delegate_t* owned_delegate; +}; + +class ScannerDelegate final : public IESScannerDelegate { + private: + void* _target; + delegate_cb_with_error_code _did_encounter_device_communication_error_cb; + delegate_cb_with_button _did_press_button_cb; + delegate_cb _will_begin_continuous_scanning_cb; + delegate_cb _did_end_continuous_scanning_cb; + // delegate_cb_with_image will_scan_to_scanned_image(...) + // delegate_cb_with_image did_scan_to_scanned_image(...) + delegate_cb _will_cancel_scanning_cb; + delegate_cb _did_cancel_scanning_cb; + delegate_cb_with_error_code _did_complete_scanning_with_error_cb; + delegate_cb_with_error_code _did_interrupt_scanning_with_error_cb; + delegate_cb _will_warm_up_cb; + delegate_cb _did_warm_up_cb; + delegate_cb _network_did_request_start_scanning_cb; + delegate_cb _network_did_request_stop_scanning_cb; + delegate_cb _did_disconnect_cb; + delegate_cb _network_did_receive_server_error_cb; + delegate_cb_ret_bool _network_should_prevent_timeout_cb; + delegate_cb _network_did_timeout_cb; + delegate_cb_with_cstr _is_reserved_by_host_cb; + delegate_cb _did_request_stop_cb; + delegate_cb _did_request_push_scan_connection_cb; + delegate_cb _did_notify_status_change_cb; + + public: + //~ScannerDelegate() {} + ScannerDelegate() {} + void Initialize( + delegate_cb_with_error_code did_encounter_device_communication_error_cb, + delegate_cb_with_button did_press_button_cb, + delegate_cb will_begin_continuous_scanning_cb, + delegate_cb did_end_continuous_scanning_cb, + delegate_cb will_cancel_scanning_cb, delegate_cb did_cancel_scanning_cb, + delegate_cb_with_error_code did_complete_scanning_with_error_cb, + delegate_cb_with_error_code did_interrupt_scanning_with_error_cb, + delegate_cb will_warm_up_cb, delegate_cb did_warm_up_cb, + delegate_cb network_did_request_start_scanning_cb, + delegate_cb network_did_request_stop_scanning_cb, + delegate_cb did_disconnect_cb, + delegate_cb network_did_receive_server_error_cb, + delegate_cb_ret_bool network_should_prevent_timeout_cb, + delegate_cb network_did_timeout_cb, + delegate_cb_with_cstr is_reserved_by_host_cb, + delegate_cb did_request_stop_cb, + delegate_cb did_request_push_scan_connection_cb, + delegate_cb did_notify_status_change_cb) { + this->_did_encounter_device_communication_error_cb = + did_encounter_device_communication_error_cb; + this->_did_press_button_cb = did_press_button_cb; + this->_will_begin_continuous_scanning_cb = + will_begin_continuous_scanning_cb; + this->_did_end_continuous_scanning_cb = did_end_continuous_scanning_cb; + this->_will_cancel_scanning_cb = will_cancel_scanning_cb; + this->_did_cancel_scanning_cb = did_cancel_scanning_cb; + this->_did_complete_scanning_with_error_cb = + did_complete_scanning_with_error_cb; + this->_did_interrupt_scanning_with_error_cb = + did_interrupt_scanning_with_error_cb; + this->_will_warm_up_cb = will_warm_up_cb; + this->_did_warm_up_cb = did_warm_up_cb; + this->_network_did_request_start_scanning_cb = + network_did_request_start_scanning_cb; + this->_network_did_request_stop_scanning_cb = + network_did_request_stop_scanning_cb; + this->_did_disconnect_cb = did_disconnect_cb; + this->_network_did_receive_server_error_cb = + network_did_receive_server_error_cb; + this->_network_should_prevent_timeout_cb = + network_should_prevent_timeout_cb; + this->_network_did_timeout_cb = network_did_timeout_cb; + this->_is_reserved_by_host_cb = is_reserved_by_host_cb; + this->_did_request_stop_cb = did_request_stop_cb; + this->_did_request_push_scan_connection_cb = + did_request_push_scan_connection_cb; + this->_did_notify_status_change_cb = did_notify_status_change_cb; + }; + + void SetCtx(void* ctx); + + void ScannerDidEncounterDeviceCommunicationError(IESScanner* pScanner, + ESErrorCode err) override; + void ScannerDidPressButton(UInt8 un8ButtonNumber) override; + void ScannerWillBeginContinuousScanning(IESScanner* pScanner) override; + void ScannerDidEndContinuousScanning(IESScanner* pScanner) override; + void ScannerWillScanToScannedImage(IESScanner* pScanner, + IESScannedImage* pESImage) override; + void ScannerDidScanToScannedImage(IESScanner* pScanner, + IESScannedImage* pESImage) override; + void ScannerWillCancelScanning(IESScanner* pScanner) override; + void ScannerDidCancelScanning(IESScanner* pScanner) override; + void ScannerDidCompleteScanningWithError(IESScanner* pScanner, + ESErrorCode err) override; + void ScannerDidInterruptScanningWithError(IESScanner* pScanner, + ESErrorCode err) override; + void ScannerWillWarmUp(IESScanner* pScanner) override; + void ScannerDidWarmUp(IESScanner* pScanner) override; + void NetworkScannerDidRequestStartScanning(IESScanner* pScanner) override; + void NetworkScannerDidRequestStopScanning(IESScanner* pScanner) override; + void ScannerDidDisconnect(IESScanner* pScanner) override; + void NetworkScannerDidReceiveServerError(IESScanner* pScanner) override; + BOOL NetworkScannerShouldPreventTimeout(IESScanner* pScanner) override; + void NetworkScannerDidTimeout(IESScanner* pScanner) override; + void ScannerIsReservedByHost(IESScanner* pScanner, + const ES_CHAR* pszAddress) override; + void ScannerDidRequestStop(IESScanner* pScanner) override; + void ScannerDidRequestPushScanConnection(IESScanner* pScanner) override; + void ScannerDidNotifyStatusChange(IESScanner* pScanner) override; +}; + +struct delegate { + ScannerDelegate* obj; + void* ctx; +}; diff --git a/es2command-sys/cinterface/src/scanner.cpp b/es2command-sys/cinterface/src/scanner.cpp new file mode 100644 index 0000000..35df1e6 --- /dev/null +++ b/es2command-sys/cinterface/src/scanner.cpp @@ -0,0 +1,387 @@ +#include +#include +#include +#include + +#include + +// these are from the epsonscan2 src +#include "ES2Command/IESScanner.h" +#include "common.hpp" +#include "internal.hpp" +#include "scanner.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +bool scanner_eq(scanner_t* a, scanner_t* b) { return a->obj == b->obj; } + +void scanner_set_delegate(scanner_t* scanner, delegate_t* delegate) { + if (scanner == NULL) { + return; + } + scanner->owned_delegate = delegate; + + static_cast(scanner->obj)->SetDelegate(delegate->obj); +} + +ESErrorCode scanner_set_connection(scanner_t* scanner, const char* json) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->SetConnection(json); +} + +delegate_t* scanner_destroy_instance(scanner_t* scanner) { + if (scanner == NULL) { + return NULL; + } + + static_cast(scanner->obj)->DestroyInstance(); + delegate_t* delegate = scanner->owned_delegate; + scanner->owned_delegate = NULL; + return delegate; +} + +ESErrorCode scanner_open(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Open(); +} + +ESErrorCode scanner_close(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Close(); +} + +bool scanner_is_opened(scanner_t* scanner) { + if (scanner == NULL) { + return false; + } + + return static_cast(scanner->obj)->IsOpened(); +} + +ESErrorCode scanner_scan(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Scan(); +} + +ESErrorCode scanner_scan_in_background(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->ScanInBackground(); +} + +ESErrorCode scanner_cancel(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Cancel(); +} + +ESErrorCode scanner_abort(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Abort(); +} + +bool scanner_is_scanning(scanner_t* scanner) { + if (scanner == NULL) { + return false; + } + + return static_cast(scanner->obj)->IsScanning(); +} + +ESErrorCode scanner_do_cleaning(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->DoCleaning(); +} + +ESErrorCode scanner_do_calibration(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->DoCalibration(); +} + +bool scanner_is_interrupted(scanner_t* scanner) { + if (scanner == NULL) { + return false; + } + + return static_cast(scanner->obj)->IsInterrupted(); +} + +bool scanner_is_afm_enabled(scanner_t* scanner) { + if (scanner == NULL) { + return false; + } + + return static_cast(scanner->obj)->IsAfmEnabled(); +} + +ESErrorCode scanner_schedule_auto_feeding_mode_timeout(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj) + ->ScheduleAutoFeedingModeTimeout(); +} + +ESErrorCode scanner_start_job_in_mode(scanner_t* scanner, uint8_t eJobMode) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->StartJobInMode(eJobMode); +} + +ESErrorCode scanner_stop_job_in_mode(scanner_t* scanner, uint8_t eJobMode) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->StopJobInMode(eJobMode); +} + +ESErrorCode scanner_do_auto_focus(scanner_t* scanner, float* pfOutFocus) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->DoAutoFocus(pfOutFocus); +} + +ESErrorCode scanner_set_panel_to_push_scan_ready(scanner_t* scanner, + bool bPushScanReady) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj) + ->SetPanelToPushScanReady(bPushScanReady); +} + +bool scanner_is_scannable_device_config(scanner_t* scanner) { + if (scanner == NULL) { + return false; + } + + return static_cast(scanner->obj)->IsScannableDeviceConfig(); +} + +ESErrorCode scanner_unlock_administrator_lock(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->UnlockAdministratorLock(); +} + +ESErrorCode scanner_lock_administrator_lock(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->LockAdministratorLock(); +} + +ESErrorCode scanner_reset(scanner_t* scanner) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->Reset(); +} + +ESErrorCode scanner_get_all_keys(scanner_t* scanner, char** oJSONStr) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = static_cast(scanner->obj)->GetAllKeys(&res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + + size_t required_len = strlen(cstr) + 1; + *oJSONStr = (char*)malloc(required_len); + + memcpy(*oJSONStr, cstr, required_len); + return err; +} + +ESErrorCode scanner_get_default_value_for_key(scanner_t* scanner, + const char* key, + char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = + static_cast(scanner->obj)->GetDefaultValueForKey(key, &res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +ESErrorCode scanner_get_value_for_key(scanner_t* scanner, const char* key, + char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = + static_cast(scanner->obj)->GetValueForKey(key, &res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +ESErrorCode scanner_set_value_for_key(scanner_t* scanner, const char* pszKey, + const char* pszJSON) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj) + ->SetValueForKey(pszKey, pszJSON); +} + +ESErrorCode scanner_set_values_with_JSON(scanner_t* scanner, + const char* pszJSON) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + return static_cast(scanner->obj)->SetValuesWithJSON(pszJSON); +} + +ESErrorCode scanner_get_all_values_for_key(scanner_t* scanner, const char* key, + char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = + static_cast(scanner->obj)->GetAllValuesForKey(key, &res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +ESErrorCode scanner_get_all_values(scanner_t* scanner, char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = static_cast(scanner->obj)->GetAllValues(&res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +ESErrorCode scanner_get_available_values_for_key(scanner_t* scanner, + const char* key, + char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = static_cast(scanner->obj) + ->GetAvailableValuesForKey(key, &res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +ESErrorCode scanner_get_all_available_values(scanner_t* scanner, + char** pstrResult) { + if (scanner == NULL) { + return ESErrorCode::kESErrorFatalError; + } + + CESResultString res; + ESErrorCode err = + static_cast(scanner->obj)->GetAllAvailableValues(&res); + if (err != kESErrorNoError) { + return err; + } + + const char* cstr = res.Get(); + size_t required_len = strlen(cstr) + 1; + *pstrResult = (char*)malloc(required_len); + memcpy(*pstrResult, cstr, required_len); + + return err; +} + +#ifdef __cplusplus +} +#endif diff --git a/es2command-sys/cinterface/src/wrapper.cpp b/es2command-sys/cinterface/src/wrapper.cpp new file mode 100644 index 0000000..11e1bb9 --- /dev/null +++ b/es2command-sys/cinterface/src/wrapper.cpp @@ -0,0 +1,23 @@ +#include "wrapper.hpp" + +#include + +#include "ES2Command/ES2CommandAPI.h" +#include "ES2Command/ESCommandProperties.h" +#include "internal.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + +ESErrorCode scanner_create(PFN_CREATE_SCANNER fptr, ESCommandType commandType, + scanner_t** ppScanner) { + *ppScanner = (scanner_t*)malloc(sizeof(scanner_t)); + return fptr(commandType, &((*ppScanner)->obj)); +} + +void scanner_free(scanner_t* scanner) { free(scanner); } + +#ifdef __cplusplus +} +#endif diff --git a/es2command-sys/src/lib.rs b/es2command-sys/src/lib.rs new file mode 100644 index 0000000..a38a13a --- /dev/null +++ b/es2command-sys/src/lib.rs @@ -0,0 +1,5 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/es2command/Cargo.toml b/es2command/Cargo.toml new file mode 100644 index 0000000..563c19c --- /dev/null +++ b/es2command/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "es2command" +version = "0.0.1" +authors = ["Jan Rüth "] +edition = "2021" +license = "MIT" +description = "Use buttons on epsonscan-supported scanners" +publish = false + +[dependencies] +libc = "0.2" +es2command-sys = { path = "../es2command-sys" } +foreign-types = "0.5" +libloading = "0.8" +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0" } +thiserror = "1.0" \ No newline at end of file diff --git a/es2command/src/delegate.rs b/es2command/src/delegate.rs new file mode 100644 index 0000000..0cd1e75 --- /dev/null +++ b/es2command/src/delegate.rs @@ -0,0 +1,369 @@ +use std::{ffi::CStr, marker::PhantomData, ptr::NonNull}; + +use crate::{ESError, ScannerRef}; +use es2command_sys::ESErrorCode; +use foreign_types::{foreign_type, ForeignTypeRef}; +use libc::c_void; + +pub trait ScanDelegate { + fn did_encounter_device_communication_error(&self, scanner: &ScannerRef, error: ESError); + fn did_press_button(&self, button: u8); + fn will_begin_continous_scanning(&self, scanner: &ScannerRef); + fn did_end_continuous_scanning(&self, scanner: &ScannerRef); + fn will_cancel_scanning(&self, scanner: &ScannerRef); + fn did_cancel_scanning(&self, scanner: &ScannerRef); + fn did_complete_scanning_with_error(&self, scanner: &ScannerRef, error: ESError); + fn did_interrupt_scanning_with_error(&self, scanner: &ScannerRef, error: ESError); + fn will_warm_up(&self, scanner: &ScannerRef); + fn did_warm_up(&self, scanner: &ScannerRef); + fn network_did_request_start_scanning(&self, scanner: &ScannerRef); + fn network_did_request_stop_scanning(&self, scanner: &ScannerRef); + fn did_disconnect(&self, scanner: &ScannerRef); + fn network_did_receive_server_error(&self, scanner: &ScannerRef); + fn network_should_prevent_timeout(&self, scanner: &ScannerRef) -> bool; + fn network_did_timeout(&self, scanner: &ScannerRef); + fn is_reserved_by_host(&self, scanner: &ScannerRef, host: String); + fn network_did_request_stop(&self, scanner: &ScannerRef); + fn network_did_request_push_scan_connection(&self, scanner: &ScannerRef); + fn network_did_notify_status_change(&self, scanner: &ScannerRef); +} + +foreign_type! { + pub unsafe type Delegate: Sync + Send + { + type CType = es2command_sys::delegate_t; + type PhantomData = T; + fn drop = es2command_sys::delegate_free; + } +} + +impl Delegate { + pub fn new(delegate: T) -> Self { + let delegate = Box::new(delegate); + Self( + NonNull::new(unsafe { + es2command_sys::delegate_new( + Box::into_raw(delegate) as _, + Some(Self::did_encounter_device_communication_error), + Some(Self::did_press_button), + Some(Self::will_begin_continous_scanning), + Some(Self::did_end_continuous_scanning), + Some(Self::will_cancel_scanning), + Some(Self::did_cancel_scanning), + Some(Self::did_complete_scanning_with_error), + Some(Self::did_interrupt_scanning_with_error), + Some(Self::will_warm_up), + Some(Self::did_warm_up), + Some(Self::network_did_request_start_scanning), + Some(Self::network_did_request_stop_scanning), + Some(Self::did_disconnect), + Some(Self::network_did_receive_server_error), + Some(Self::network_should_prevent_timeout), + Some(Self::network_did_timeout), + Some(Self::is_reserved_by_host), + Some(Self::network_did_request_stop), + Some(Self::network_did_request_push_scan_connection), + Some(Self::network_did_notify_status_change), + ) + }) + .unwrap(), + PhantomData, + ) + } + + unsafe fn delegate_from_target(target: &*mut c_void) -> &T { + &*(*target as *mut T) + } + + extern "C" fn did_encounter_device_communication_error( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + error: ESErrorCode, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + + target.did_encounter_device_communication_error(scanner, ESError::from(error)); + } + + extern "C" fn did_press_button(target: *mut c_void, button: u8) { + let target = unsafe { Self::delegate_from_target(&target) }; + target.did_press_button(button) + } + + extern "C" fn will_begin_continous_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.will_begin_continous_scanning(scanner) + } + extern "C" fn did_end_continuous_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_end_continuous_scanning(scanner) + } + + extern "C" fn will_cancel_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.will_cancel_scanning(scanner) + } + + extern "C" fn did_cancel_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_cancel_scanning(scanner) + } + + extern "C" fn did_complete_scanning_with_error( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + error: ESErrorCode, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_complete_scanning_with_error(scanner, ESError::from(error)) + } + + extern "C" fn did_interrupt_scanning_with_error( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + error: ESErrorCode, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_interrupt_scanning_with_error(scanner, ESError::from(error)) + } + extern "C" fn will_warm_up(target: *mut c_void, scanner: *mut es2command_sys::scanner_t) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.will_warm_up(scanner) + } + extern "C" fn did_warm_up(target: *mut c_void, scanner: *mut es2command_sys::scanner_t) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_warm_up(scanner) + } + extern "C" fn network_did_request_start_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_request_start_scanning(scanner) + } + + extern "C" fn network_did_request_stop_scanning( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_request_stop_scanning(scanner) + } + + extern "C" fn did_disconnect(target: *mut c_void, scanner: *mut es2command_sys::scanner_t) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.did_disconnect(scanner) + } + + extern "C" fn network_did_receive_server_error( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_receive_server_error(scanner) + } + + extern "C" fn network_should_prevent_timeout( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) -> bool { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + + target.network_should_prevent_timeout(scanner) + } + + extern "C" fn network_did_timeout( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_timeout(scanner) + } + + extern "C" fn is_reserved_by_host( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + host: *const core::ffi::c_char, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + let host = unsafe { CStr::from_ptr(host) }.to_str().unwrap().to_owned(); + target.is_reserved_by_host(scanner, host) + } + + extern "C" fn network_did_request_stop( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_request_stop(scanner) + } + + extern "C" fn network_did_request_push_scan_connection( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_request_push_scan_connection(scanner) + } + + extern "C" fn network_did_notify_status_change( + target: *mut c_void, + scanner: *mut es2command_sys::scanner_t, + ) { + let (target, scanner) = unsafe { + ( + Self::delegate_from_target(&target), + ScannerRef::from_ptr(scanner), + ) + }; + target.network_did_notify_status_change(scanner) + } +} + +pub(crate) struct NonDelegate(); + +impl ScanDelegate for NonDelegate { + fn did_encounter_device_communication_error(&self, _scanner: &ScannerRef, _error: ESError) {} + + fn did_press_button(&self, _button: u8) {} + + fn will_begin_continous_scanning(&self, _scanner: &ScannerRef) {} + + fn did_end_continuous_scanning(&self, _scanner: &ScannerRef) {} + + fn will_cancel_scanning(&self, _scanner: &ScannerRef) {} + + fn did_cancel_scanning(&self, _scanner: &ScannerRef) {} + + fn did_complete_scanning_with_error(&self, _scanner: &ScannerRef, _error: ESError) {} + + fn did_interrupt_scanning_with_error(&self, _scanner: &ScannerRef, _rror: ESError) {} + + fn will_warm_up(&self, _scanner: &ScannerRef) {} + + fn did_warm_up(&self, _scanner: &ScannerRef) {} + + fn network_did_request_start_scanning(&self, _scanner: &ScannerRef) {} + + fn network_did_request_stop_scanning(&self, _scanner: &ScannerRef) {} + + fn did_disconnect(&self, _scanner: &ScannerRef) {} + + fn network_did_receive_server_error(&self, _scanner: &ScannerRef) {} + + fn network_should_prevent_timeout(&self, _scanner: &ScannerRef) -> bool { + false + } + + fn network_did_timeout(&self, _scanner: &ScannerRef) {} + + fn is_reserved_by_host(&self, _scanner: &ScannerRef, _host: String) {} + + fn network_did_request_stop(&self, _scanner: &ScannerRef) {} + + fn network_did_request_push_scan_connection(&self, _scanner: &ScannerRef) {} + + fn network_did_notify_status_change(&self, _scanner: &ScannerRef) {} +} diff --git a/es2command/src/helper.rs b/es2command/src/helper.rs new file mode 100644 index 0000000..0b79cb9 --- /dev/null +++ b/es2command/src/helper.rs @@ -0,0 +1,8 @@ +use crate::ESError; + +pub(crate) fn cvt(error_code: es2command_sys::ESErrorCode) -> Result<(), ESError> { + match ESError::from(error_code) { + ESError::NoError => Ok(()), + x => Err(x), + } +} diff --git a/es2command/src/lib.rs b/es2command/src/lib.rs new file mode 100644 index 0000000..6d7eeab --- /dev/null +++ b/es2command/src/lib.rs @@ -0,0 +1,8 @@ +mod delegate; +mod helper; +mod scanner; +mod types; + +pub use delegate::*; +pub use scanner::*; +pub use types::*; diff --git a/es2command/src/scanner.rs b/es2command/src/scanner.rs new file mode 100644 index 0000000..0cdf239 --- /dev/null +++ b/es2command/src/scanner.rs @@ -0,0 +1,349 @@ +use std::{ + ffi::{CStr, CString}, + mem::MaybeUninit, + path::{Path, PathBuf}, + str::FromStr, +}; + +use crate::{helper::cvt, Delegate, ESError, ESJobMode, NonDelegate, ScanDelegate}; +use es2command_sys::ESCommandType; +use foreign_types::{foreign_type, ForeignType, ForeignTypeRef}; +use libloading::Symbol; + +foreign_type! { + + pub unsafe type Scanner: Sync + Send + { + type CType = es2command_sys::scanner_t; + fn drop = scanner_free; + } +} + +unsafe fn scanner_free(scanner: *mut es2command_sys::scanner_t) { + let delegate = es2command_sys::scanner_destroy_instance(scanner); + // if the scanner had a delegate + // we now own it, so we need to release it as well + if !delegate.is_null() { + let _ = Delegate::::from_ptr(delegate); + } + es2command_sys::scanner_free(scanner) +} + +impl Default for Scanner { + fn default() -> Self { + let install_dir = + unsafe { CStr::from_ptr(es2command_sys::DEFAULT_INSTALL_LIB_DIR[..].as_ptr() as _) }; + let library_path = PathBuf::from_str(install_dir.to_str().unwrap()) + .unwrap() + .join("libes2command.so"); + Self::new(&library_path, ESCommandType::kESCommandTypeESCI2).unwrap() + } +} + +impl Scanner { + pub fn new(library_path: &Path, cmd_type: ESCommandType) -> Result { + let library = unsafe { libloading::Library::new(library_path) }.unwrap(); + let es_create_scanner: Symbol = + unsafe { library.get(es2command_sys::DEFAULT_ES_CREATE_SCANNER_SYMBOL_NAME) }.unwrap(); + + Ok(unsafe { + let mut scanner: MaybeUninit<*mut es2command_sys::scanner_t> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_create( + *es_create_scanner, + cmd_type, + scanner.as_mut_ptr(), + ))?; + + Self::from_ptr(scanner.assume_init()) + }) + } +} + +impl ScannerRef { + pub fn set_delegate(&self, delegate: T) { + let delegate = Delegate::new(delegate); + // es2command_sys owns the delegate memory from here + unsafe { es2command_sys::scanner_set_delegate(self.as_ptr(), delegate.into_ptr()) } + } + + pub fn set_connection(&self, json: &str) -> Result<(), ESError> { + let json = CString::new(json).unwrap(); + unsafe { + cvt(es2command_sys::scanner_set_connection( + self.as_ptr(), + json.as_ptr(), + )) + } + } + + pub fn open(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_open(self.as_ptr()) }) + } + + pub fn close(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_close(self.as_ptr()) }) + } + + pub fn is_opened(&self) -> bool { + unsafe { es2command_sys::scanner_is_opened(self.as_ptr()) } + } + + pub fn scan(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_scan(self.as_ptr()) }) + } + pub fn scan_in_background(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_scan_in_background(self.as_ptr()) }) + } + + pub fn cancel(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_cancel(self.as_ptr()) }) + } + + pub fn abort(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_abort(self.as_ptr()) }) + } + + pub fn is_scanning(&self) -> bool { + unsafe { es2command_sys::scanner_is_scanning(self.as_ptr()) } + } + + pub fn do_cleaning(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_do_cleaning(self.as_ptr()) }) + } + + pub fn do_calibration(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_do_calibration(self.as_ptr()) }) + } + + pub fn is_interrupted(&self) -> bool { + unsafe { es2command_sys::scanner_is_interrupted(self.as_ptr()) } + } + + pub fn is_afm_enabled(&self) -> bool { + unsafe { es2command_sys::scanner_is_afm_enabled(self.as_ptr()) } + } + + pub fn schedule_auto_feeding_mode_timeout(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_schedule_auto_feeding_mode_timeout(self.as_ptr()) }) + } + + pub fn start_job_in_mode(&self, mode: ESJobMode) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_start_job_in_mode(self.as_ptr(), mode as u8) }) + } + + pub fn stop_job_in_mode(&self, mode: ESJobMode) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_stop_job_in_mode(self.as_ptr(), mode as u8) }) + } + + pub fn do_auto_focus(&self) -> Result { + let mut focus = 0.0; + cvt(unsafe { es2command_sys::scanner_do_auto_focus(self.as_ptr(), &mut focus) })?; + Ok(focus) + } + + pub fn set_panel_to_push_scan_ready(&self, push_scan_read: bool) -> Result<(), ESError> { + cvt(unsafe { + es2command_sys::scanner_set_panel_to_push_scan_ready(self.as_ptr(), push_scan_read) + }) + } + + pub fn is_scannable_device_config(&self) -> bool { + unsafe { es2command_sys::scanner_is_scannable_device_config(self.as_ptr()) } + } + + pub fn unlock_administrator_lock(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_unlock_administrator_lock(self.as_ptr()) }) + } + + pub fn lock_administrator_lock(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_lock_administrator_lock(self.as_ptr()) }) + } + + pub fn reset(&self) -> Result<(), ESError> { + cvt(unsafe { es2command_sys::scanner_reset(self.as_ptr()) }) + } + + pub fn get_all_keys(&self) -> Result { + let cstr = unsafe { + let mut keys: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_all_keys( + self.as_ptr(), + keys.as_mut_ptr(), + ))?; + CStr::from_ptr(keys.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_default_value_for_key(&self, key: &str) -> Result { + let key = CString::new(key).unwrap(); + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_default_value_for_key( + self.as_ptr(), + key.as_ptr(), + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_value_for_key(&self, key: &str) -> Result { + let key = CString::new(key).unwrap(); + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_value_for_key( + self.as_ptr(), + key.as_ptr() as _, + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_bool_value_for_key(&self, key: &str) -> Result { + let value = self.get_value_for_key(key)?; + // this returns {"$key": {"boolean": false|true}} + let value: serde_json::Value = + serde_json::from_str(&value).map_err(|_| ESError::InvalidResponse)?; + + value + .as_object() + .and_then(|f| f.get(key)) + .and_then(|f| f.as_object()) + .and_then(|f| f.get("boolean")) + .and_then(|f| f.as_bool()) + .ok_or(ESError::InvalidResponse) + } + + pub fn set_value_for_key(&mut self, key: &str, value: &str) -> Result<(), ESError> { + let key = CString::new(key).unwrap(); + let value = CString::new(value).unwrap(); + unsafe { + cvt(es2command_sys::scanner_set_value_for_key( + self.as_ptr(), + key.as_ptr(), + value.as_ptr(), + )) + } + } + pub fn set_values_with_json(&mut self, json: &str) -> Result<(), ESError> { + let json = CString::new(json).unwrap(); + + unsafe { + cvt(es2command_sys::scanner_set_values_with_JSON( + self.as_ptr(), + json.as_ptr(), + )) + } + } + + pub fn get_all_values_for_key(&self, key: &str) -> Result { + let key = CString::new(key).unwrap(); + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_all_values_for_key( + self.as_ptr(), + key.as_ptr() as _, + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_all_values(&self) -> Result { + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_all_values( + self.as_ptr(), + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_available_values_for_key(&self, key: &str) -> Result { + let key = CString::new(key).unwrap(); + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_available_values_for_key( + self.as_ptr(), + key.as_ptr() as _, + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } + + pub fn get_all_available_values(&self) -> Result { + let cstr = unsafe { + let mut value: MaybeUninit<*mut core::ffi::c_char> = MaybeUninit::uninit(); + cvt(es2command_sys::scanner_get_all_available_values( + self.as_ptr(), + value.as_mut_ptr(), + ))?; + CStr::from_ptr(value.assume_init()) + }; + let out = cstr + .to_str() + .map_err(|_| ESError::InvalidResponse) + .map(|x| x.to_owned()); + unsafe { + libc::free(cstr.as_ptr() as _); + } + out + } +} + +impl PartialEq for ScannerRef { + fn eq(&self, other: &Self) -> bool { + unsafe { es2command_sys::scanner_eq(self.as_ptr(), other.as_ptr()) } + } +} diff --git a/es2command/src/types.rs b/es2command/src/types.rs new file mode 100644 index 0000000..dd5080d --- /dev/null +++ b/es2command/src/types.rs @@ -0,0 +1,205 @@ +use serde::Serialize; +use thiserror::Error; + +// Reexport types +pub use es2command_sys::ESConnectionType; + +#[macro_export] +macro_rules! str_from_cstr { + ($lit:expr) => { + if let Some((_, x)) = $lit.split_last() { + unsafe { std::str::from_utf8_unchecked(x) } + } else { + "" + } + }; +} +pub const ESKEY_DOCUMENT_LOADED: &str = str_from_cstr!(es2command_sys::kESDocumentLoaded); +pub const ESKEY_CARD_SCANNING: &str = str_from_cstr!(es2command_sys::kESCardScanning); + +#[derive(Error, Debug)] +pub enum ESError { + #[error("Success")] + NoError, + #[error("Fatal Error")] + FatalError, + #[error("Invalid Parameter")] + InvalidParameter, + + // Driver internal error + #[error("internal error: memory error")] + MemoryError, + #[error("internal error: sequence error")] + SequenceError, + #[error("internal error: file write error")] + FileWriteError, + #[error("internal error: file read error")] + FileReadError, + #[error("internal error: scan area too large error")] + ScanAreaTooLargeError, + + // Communication error + #[error("communication error: data send failure")] + DataSendFailure, // データー転送エラー + #[error("communication error: data receive failure")] + DataReceiveFailure, // データー受信エラー + #[error("communication error: invalid response")] + InvalidResponse, // 不正なレスポンス + #[error("communication error: device open error")] + DeviceOpenError, + + // Device error + #[error("device error: device in use")] + DeviceInUse, + #[error("device error: device busy")] + DeviceInBusy, + #[error("device error: paper empty")] + PaperEmpty, + #[error("device error: paper jam")] + PaperJam, + #[error("device error: paper double feed")] + PaperDoubleFeed, + #[error("device error: cover open")] + CoverOpen, + #[error("device error: tray close")] + TrayClose, + #[error("device error: cr lock")] + CRLock, + #[error("device error: lamp error")] + LampError, + #[error("device error: lamp time")] + LampTime, + #[error("device error: auth failure")] + AuthFailure, + #[error("device error: no permission")] + NoPermission, + #[error("device error: low battery")] + LowBattery, + #[error("device error: focus error")] + FocusError, + #[error("device error: fatal error")] + DeviceFatalError, + #[error("device error: cr sheet sensor error")] + CRSheetSensorError, + #[error("device error: paper protect")] + PaperProtect, + #[error("device error: gap sensor error")] + GAPSensorError, + #[error("device error: paper double feed 2")] + PaperDoubleFeed2, + #[error("device error: pose error")] + PoseError, + #[error("device error: separation level error")] + SeparationLeverError, + #[error("device error: et sensor error")] + ETSensorError, + #[error("device error: adf lift error")] + ADFLiftError, + #[error("device error: user auth enabled")] + UserAuthEnabled, + #[error("device error: print stacker error")] + PrintStackerError, + #[error("device error: paper remove error")] + PaperRemoveError, + #[error("device error: skew detect error")] + SkewDetectError, + + #[error("unknown error: {0}")] + UnknownError(u32), +} + +impl From for ESError { + fn from(value: es2command_sys::ESErrorCode) -> Self { + match value { + es2command_sys::ESErrorCode::kESErrorNoError => ESError::NoError, + + es2command_sys::ESErrorCode::kESErrorFatalError => ESError::FatalError, + es2command_sys::ESErrorCode::kESErrorInvalidParameter => ESError::InvalidParameter, + + es2command_sys::ESErrorCode::kESErrorMemoryError => ESError::MemoryError, + es2command_sys::ESErrorCode::kESErrorSequenceError => ESError::SequenceError, + es2command_sys::ESErrorCode::kESErrorFileWriteError => ESError::FileWriteError, + es2command_sys::ESErrorCode::kESErrorFileReadError => ESError::FileReadError, + es2command_sys::ESErrorCode::kESErrorScanAreaTooLargeError => { + ESError::ScanAreaTooLargeError + } + + es2command_sys::ESErrorCode::kESErrorDataSendFailure => ESError::DataSendFailure, + es2command_sys::ESErrorCode::kESErrorDataReceiveFailure => ESError::DataReceiveFailure, + es2command_sys::ESErrorCode::kESErrorInvalidResponse => ESError::InvalidResponse, + es2command_sys::ESErrorCode::kESErrorDeviceOpenError => ESError::DeviceOpenError, + + es2command_sys::ESErrorCode::kESErrorDeviceInUse => ESError::DeviceInUse, + es2command_sys::ESErrorCode::kESErrorDeviceInBusy => ESError::DeviceInBusy, + es2command_sys::ESErrorCode::kESErrorPaperEmpty => ESError::PaperEmpty, + es2command_sys::ESErrorCode::kESErrorPaperJam => ESError::PaperJam, + es2command_sys::ESErrorCode::kESErrorPaperDoubleFeed => ESError::PaperDoubleFeed, + es2command_sys::ESErrorCode::kESErrorCoverOpen => ESError::CoverOpen, + es2command_sys::ESErrorCode::kESErrorTrayClose => ESError::TrayClose, + es2command_sys::ESErrorCode::kESErrorCRLock => ESError::CRLock, + es2command_sys::ESErrorCode::kESErrorLampError => ESError::LampError, + es2command_sys::ESErrorCode::kESErrorLampTime => ESError::LampTime, + es2command_sys::ESErrorCode::kESErrorAuthFailure => ESError::AuthFailure, + es2command_sys::ESErrorCode::kESErrorNoPermission => ESError::NoPermission, + es2command_sys::ESErrorCode::kESErrorLowBattery => ESError::LowBattery, + es2command_sys::ESErrorCode::kESErrorFocusError => ESError::FocusError, + es2command_sys::ESErrorCode::kESErrorDeviceFatalError => ESError::DeviceFatalError, + es2command_sys::ESErrorCode::kESErrorCRSheetSensorError => ESError::CRSheetSensorError, + es2command_sys::ESErrorCode::kESErrorPaperProtect => ESError::PaperProtect, + es2command_sys::ESErrorCode::kESErrorGAPSensorError => ESError::GAPSensorError, + es2command_sys::ESErrorCode::kESErrorPaperDoubleFeed2 => ESError::PaperDoubleFeed2, + es2command_sys::ESErrorCode::kESErrorPoseError => ESError::PoseError, + es2command_sys::ESErrorCode::kESErrorSeparationLeverError => { + ESError::SeparationLeverError + } + es2command_sys::ESErrorCode::kESErrorETSensorError => ESError::ETSensorError, + es2command_sys::ESErrorCode::kESErrorADFLiftError => ESError::ADFLiftError, + es2command_sys::ESErrorCode::kESErrorUserAuthEnabled => ESError::UserAuthEnabled, + es2command_sys::ESErrorCode::kESErrorPrintStackerError => ESError::PrintStackerError, + es2command_sys::ESErrorCode::kESErrorPaperRemoveError => ESError::PaperRemoveError, + es2command_sys::ESErrorCode::kESErrorSkewDetectError => ESError::SkewDetectError, + //v => ESError::UnknownError(v as u32), + } + } +} + +#[repr(u8)] +pub enum ESJobMode { + None = es2command_sys::kESJobModeNone as u8, + Standard = es2command_sys::kESJobModeStandard as u8, + Continue = es2command_sys::kESJobModeContinue as u8, + AFM = es2command_sys::kESJobModeAFM as u8, + AFMC = es2command_sys::kESJobModeAFMC as u8, +} + +#[derive(Debug, Serialize)] +pub enum TypeInt { + #[serde(rename = "int")] + Int(T), +} + +#[derive(Debug, Serialize)] +pub struct ConnectionSettings { + /// Encoded as [`es2command_sys::ES_CNCT_KEY_TYPE`] + #[serde(rename = "ConnectType")] + pub connect_type: TypeInt, + /// Encoded as [`es2command_sys::ES_CNCT_KEY_VID`] + #[serde(rename = "VID")] + pub vid: TypeInt, + /// Encoded as [`es2command_sys::ES_CNCT_KEY_PID`] + #[serde(rename = "PID")] + pub pid: TypeInt, + /// Encoded as [`es2command_sys::ES_CNCT_KEY_BUS_NUMBER`] + #[serde(rename = "BUS_NUMBER")] + pub bus_number: TypeInt, + /// Encoded as [`es2command_sys::ES_CNCT_KEY_DEVICE_NUMBER`] + #[serde(rename = "DEVICE_NUMBER")] + pub device_number: TypeInt, +} + +#[derive(Debug, Serialize)] +pub struct UsbConnectInfo { + /// Encoded as [`es2command_sys::ES_CNCT_KEY_ROOT`] + #[serde(rename = "ConnectionSetting")] + pub connection_setting: Vec, +} diff --git a/example/example-scanimage.sh b/example/example-scanimage.sh index 526069e..4f3f65b 100755 --- a/example/example-scanimage.sh +++ b/example/example-scanimage.sh @@ -29,10 +29,10 @@ then # protocol=esci2 only supported by sane # transport=usb only supported # model_from_pid - scanimage -d "epsonscan2:${ES2_DEV}:esci2:usb:${model}:${pid_as_dec}" --duplex=yes --resolution=400 --scan-area A4 --deskew=yes -b "img%d.jpeg" + scanimage -d "epsonscan2:${ES2_DEV}:esci2:usb:ES${model}:${pid_as_dec}" --duplex=yes --resolution=400 --scan-area A4 --deskew=yes -b "img%d.jpeg" else echo "Scanning plastic card" - scanimage -d "epsonscan2:${ES2_DEV}:esci2:usb:${model}:${pid_as_dec}" --duplex=yes --resolution=400 --scan-area PlasticCard --deskew=yes -b "card%d.jpeg" + scanimage -d "epsonscan2:${ES2_DEV}:esci2:usb:ES${model}:${pid_as_dec}" --duplex=yes --resolution=400 --scan-area PlasticCard --deskew=yes -b "card%d.jpeg" fi echo "Finished scan" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index a75c8cb..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,448 +0,0 @@ - -#include -#include -#include - -#include -#include - -using json = nlohmann::json; - -// these are from the epsonscan2 src -#include -#include - -// this is generated by cmake -#include - -void print_usage(char* argv[]) { - printf("Usage: %s [-l] [-d DEVNAME] PROGRAM\n", argv[0]); - printf("\n"); - printf(" -l\t\tList devices\n"); - printf(" -d DEVNAME\tUse device, e.g., ES-310:006:001\n"); -} - -static const uint32_t kEpsonUSBVID = 0x04b8; - -typedef struct { - unsigned char name[255]; - int vid; - int pid; - int bus; - int dev; -} USBDevice; - -class ESListener : public IESScannerDelegate { - private: - IESScanner* _scanner; - const char* _prog; - USBDevice _dev; - PFN_CREATE_SCANNER _create_scanner_fn; - - ESErrorCode read_bool_value(const char* key, bool* b) { - CESResultString res; - ESErrorCode eErrorCode; - eErrorCode = _scanner->GetValueForKey(key, &res); - if (eErrorCode != kESErrorNoError) { - return eErrorCode; - } - json resp = json::parse(res.Get()); - *b = resp[key]["boolean"]; - return kESErrorNoError; - } - - public: - ESListener() { // Constructor - void* handle = dlopen(EPSONSCAN2_LIB_PATH "libes2command.so", RTLD_LAZY); - if (!handle) { - perror(dlerror()); - exit(EXIT_FAILURE); - } - _create_scanner_fn = (PFN_CREATE_SCANNER)dlsym(handle, "ESCreateScanner"); - if (_create_scanner_fn == NULL) { - printf("Could not find ESCreateScanner in libes2command.so"); - exit(EXIT_FAILURE); - } - } - void showGetAllAvailableValues() { - CESResultString res; - ESErrorCode eErrorCode; - eErrorCode = _scanner->GetAllAvailableValues(&res); - if (eErrorCode != kESErrorNoError) { - printf("failed GetAllAvailableValues: %d", eErrorCode); - return; - } - printf("%s\n", res.Get()); - } - - void showGetAllValues() { - CESResultString res; - ESErrorCode eErrorCode; - eErrorCode = _scanner->GetAllValues(&res); - if (eErrorCode != kESErrorNoError) { - printf("failed GetAllValues: %d", eErrorCode); - return; - } - printf("%s\n", res.Get()); - } - std::vector getEpsonDevices() { - std::vector result; - - libusb_context* pContext; - libusb_device** ppDeviceList; - libusb_device_descriptor oDeviceDescriptor; - libusb_device_handle* hHandle; - - int iReturnValue = libusb_init(&pContext); - if (iReturnValue != LIBUSB_SUCCESS) { - return result; - } - - ssize_t nbUsbDevices = libusb_get_device_list(pContext, &ppDeviceList); - - for (ssize_t i = 0; i < nbUsbDevices; ++i) { - libusb_device* pDevice = ppDeviceList[i]; - iReturnValue = libusb_get_device_descriptor(pDevice, &oDeviceDescriptor); - if (iReturnValue != LIBUSB_SUCCESS) { - continue; - } - if (oDeviceDescriptor.idVendor != kEpsonUSBVID) { - continue; - } - iReturnValue = libusb_open(pDevice, &hHandle); - if (iReturnValue != LIBUSB_SUCCESS) { - printf("failed opening usb device\n"); - continue; - } - iReturnValue = libusb_reset_device(hHandle); - if (iReturnValue != LIBUSB_SUCCESS) { - printf("failed resetting usb device\n"); - libusb_close(hHandle); - continue; - } - - USBDevice dev; - - int iProductNameSize = libusb_get_string_descriptor_ascii( - hHandle, oDeviceDescriptor.iProduct, dev.name, sizeof(dev.name)); - if (iProductNameSize <= 0) { - printf("LIBUSB ERR: %d", iProductNameSize); - memcpy(dev.name, "Failed getting name", 20); - } - - dev.bus = libusb_get_bus_number(pDevice); - dev.dev = libusb_get_device_address(pDevice); - dev.vid = oDeviceDescriptor.idVendor; - dev.pid = oDeviceDescriptor.idProduct; - - result.push_back(dev); - - libusb_close(hHandle); - } - - libusb_free_device_list(ppDeviceList, 1); - libusb_exit(pContext); - - return result; - } - ESErrorCode init(USBDevice* dev, const char* prog) { - _dev = *dev; - ESErrorCode eErrorCode = _create_scanner_fn(kESCommandTypeESCI2, &_scanner); - - if (eErrorCode != kESErrorNoError) { - perror("failed aquiring scanner engine"); - return eErrorCode; - } - - // todo discover usb devices with VID=0x04b8 - - json esDeviceDict = { - {ES_CNCT_KEY_ROOT, - {{{ES_CNCT_KEY_TYPE, {{"int", kESConnectionLocal}}}, - {ES_CNCT_KEY_VID, {{"int", _dev.vid}}}, - {ES_CNCT_KEY_PID, {{"int", _dev.pid}}}, - {ES_CNCT_KEY_BUS_NUMBER, {{"int", _dev.bus}}}, - {ES_CNCT_KEY_DEVICE_NUMBER, {{"int", _dev.dev}}}}}}}; - - std::string serialized_string = esDeviceDict.dump(1); - - _scanner->SetConnection(serialized_string.c_str()); - - _scanner->SetDelegate(this); - - _prog = prog; - - eErrorCode = _scanner->Open(); - if (eErrorCode != kESErrorNoError) { - perror("failed aquiring scanner engine"); - return eErrorCode; - } - return kESErrorNoError; - } - - void listen() { - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGPIPE); - sigprocmask(SIG_BLOCK, &set, NULL); - - int sig; - sigwait(&set, &sig); - switch (sig) { - case SIGINT: - printf("Terminating\n"); - break; - case SIGPIPE: - printf("Stopping scanner is gone\n"); - break; - } - - _scanner->Close(); - _scanner->DestroyInstance(); - } - - bool IsDocumentLoaded() { - bool res; - if (read_bool_value(kESDocumentLoaded, &res) != kESErrorNoError) { - printf("Failed checking document status\n"); - return false; - } - return res; - } - - bool IsCardScanning() { - bool res; - if (read_bool_value(kESCardScanning, &res) != kESErrorNoError) { - printf("Failed checking card scanning status\n"); - return false; - } - return res; - } - - // Delegate methods below - - void ScannerDidEncounterDeviceCommunicationError(IESScanner* pScanner, - ESErrorCode err) { - printf("Communication Error: %d\n", __PRETTY_FUNCTION__, err); - // wakeup listener - kill(getpid(), SIGPIPE); - }; - - void ScannerDidPressButton(UInt8 un8ButtonNumber) { - // printf("%s: %d was pressed\n", __PRETTY_FUNCTION__, un8ButtonNumber); - - ESErrorCode eErrorCode; - auto docLoaded = this->IsDocumentLoaded(); - auto cardScanning = this->IsCardScanning(); - - _scanner->Close(); - - char buttonNumEnvStr[4]; - - sprintf(buttonNumEnvStr, "%d", un8ButtonNumber); - setenv("ES2_BUTTON_NUM", buttonNumEnvStr, 1); // Overwrite it - setenv("ES2_DOC_PRESENT", docLoaded ? "Yes" : "No", - 1); // Overwrite it - setenv("ES2_CARD_SCANNING", cardScanning ? "Yes" : "No", - 1); // Overwrite it - - char device[sizeof(_dev.name) + 1 + 3 + 1 + 3 + 1]; // dev:000:000\0 - char vid[5]; - char pid[5]; - - sprintf(device, "%s:%03d:%03d", _dev.name, _dev.bus, _dev.dev); - sprintf(vid, "%04X", _dev.vid); - sprintf(pid, "%04X", _dev.pid); - - setenv("ES2_DEV", device, 1); // Overwrite it - setenv("ES2_DEV_VID", vid, 1); // Overwrite it - setenv("ES2_DEV_PID", pid, 1); // Overwrite it - printf("Calling script: %s\n", _prog); - - system(_prog); - - printf("Resuming from script\n"); - _scanner->Open(); - }; - - void ScannerWillBeginContinuousScanning(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidEndContinuousScanning(IESScanner* pScanenr) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerWillScanToScannedImage(IESScanner* pScanner, - IESScannedImage* pESImage) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidScanToScannedImage(IESScanner* pScanner, - IESScannedImage* pESImage) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerWillCancelScanning(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidCancelScanning(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidCompleteScanningWithError(IESScanner* pScanner, - ESErrorCode err) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidInterruptScanningWithError(IESScanner* pcScanner, - ESErrorCode err) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerWillWarmUp(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidWarmUp(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void NetworkScannerDidRequestStartScanning(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void NetworkScannerDidRequestStopScanning(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidDisconnect(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void NetworkScannerDidReceiveServerError(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - BOOL NetworkScannerShouldPreventTimeout(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - return false; - }; - - void NetworkScannerDidTimeout(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerIsReservedByHost(IESScanner* pScanner, - const ES_CHAR* pszAddress) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidRequestStop(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - - void ScannerDidRequestPushScanConnection(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; - void ScannerDidNotifyStatusChange(IESScanner* pScanner) { - printf("%s\n", __PRETTY_FUNCTION__); - }; -}; - -int main(int argc, char* argv[]) { - ESListener listener; - ESErrorCode err; - - auto devices = listener.getEpsonDevices(); - USBDevice dev; - memset(&dev, 0, sizeof(dev)); - for (;;) { - switch ( - getopt(argc, argv, "ld:h")) // note the colon (:) to indicate that 'b' - // has a parameter and is not a switch - { - case 'l': { - for (auto d : devices) { - printf("%s:%03d:%03d\n", d.name, d.bus, d.dev); - } - return 0; - } - - case 'd': { - char* dev_name = strtok(optarg, ":"); - char* dev_bus = strtok(NULL, ":"); - char* dev_dev = strtok(NULL, ":"); - - printf("%s %d %d", dev_name, atoi(dev_bus), atoi(dev_dev)); - if (devices.empty()) { - printf("No devices found\n"); - return 0; - } - - for (auto d : devices) { - if (dev_name != NULL && strcmp((const char*)d.name, dev_name) != 0) { - continue; - } - if (dev_bus != NULL && atoi(dev_bus) != d.bus) { - continue; - } - if (dev_dev != NULL && atoi(dev_dev) != d.dev) { - continue; - } - dev = d; - - break; - } - if (dev.vid == 0) { - printf("Device not found\n"); - return 1; - } - continue; - } - - case '?': - case 'h': { - print_usage(argv); - return 0; - } - - case -1: { - if (dev.vid == 0) { // no device set yet - if (devices.empty()) { - printf("No devices found\n"); - return 0; - } - dev = devices.at(0); - } - break; - } - } - break; - } - - char* prog = (char*)ES2CONF_DIR "/entrypoint"; - if (optind >= argc) { - printf("No program specified, falling back to default\n\n"); - }else { - prog = argv[optind]; - } - - printf("Using \"%s\" as program to call\n", prog); - - printf("Initializing %s, vid=%04X, pid=%04X, bus=%03d, dev=%03d\n", dev.name, - dev.vid, dev.pid, dev.bus, dev.dev); - - err = listener.init(&dev, prog); - if (err != kESErrorNoError) { - return err; - } - - // listener.showGetAllAvailableValues(); - - // listener.showGetAllValues(); - - listener.listen(); -} diff --git a/templates/config.h.in b/templates/config.h.in deleted file mode 100644 index f897122..0000000 --- a/templates/config.h.in +++ /dev/null @@ -1,2 +0,0 @@ -#cmakedefine EPSONSCAN2_LIB_PATH "@EPSONSCAN2_LIB_PATH@" -#cmakedefine ES2CONF_DIR "@ES2CONF_DIR@"