feat: initial commit
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: Consecutive
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AttributeMacros: ['CAHUTE_WUR', 'CAHUTE_DEPRECATED', 'CAHUTE_EXTERN']
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: After
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeElse: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BracedInitializerIndentWidth: 4
|
||||
BreakAfterAttributes: Never
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 79
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: NoIndent
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: true
|
||||
InsertTrailingCommas: None
|
||||
KeepEmptyLinesAtEOF: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
Language: Cpp
|
||||
LineEnding: LF
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
PPIndentWidth: 1
|
||||
PointerAlignment: Right
|
||||
QualifierAlignment: Custom
|
||||
QualifierOrder: ['constexpr', 'static', 'inline', 'type', 'volatile', 'const', 'restrict']
|
||||
ReferenceAlignment: Right
|
||||
ReflowComments: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: true
|
||||
SortIncludes: Never
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAroundPointerQualifiers: Both
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
|
@ -0,0 +1,358 @@
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/linux,osx,macos,sublimetext,kate,kdevelop4,cmake,c,python
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=linux,osx,macos,sublimetext,kate,kdevelop4,cmake,c,python
|
||||
|
||||
### C ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### CMake ###
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
### CMake Patch ###
|
||||
# External projects
|
||||
*-prefix/
|
||||
|
||||
### Kate ###
|
||||
# Swap Files #
|
||||
.*.kate-swp
|
||||
.swp.*
|
||||
|
||||
### KDevelop4 ###
|
||||
*.kdev4
|
||||
.kdev4/
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
### OSX ###
|
||||
# General
|
||||
|
||||
# Icon must end with two \r
|
||||
|
||||
# Thumbnails
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
### Python Patch ###
|
||||
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||
poetry.toml
|
||||
|
||||
# ruff
|
||||
.ruff_cache/
|
||||
|
||||
# LSP config files
|
||||
pyrightconfig.json
|
||||
|
||||
### SublimeText ###
|
||||
# Cache files for Sublime Text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
|
||||
# Workspace files are user-specific
|
||||
*.sublime-workspace
|
||||
|
||||
# Project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using Sublime Text
|
||||
# *.sublime-project
|
||||
|
||||
# SFTP configuration file
|
||||
sftp-config.json
|
||||
sftp-config-alt*.json
|
||||
|
||||
# Package control specific files
|
||||
Package Control.last-run
|
||||
Package Control.ca-list
|
||||
Package Control.ca-bundle
|
||||
Package Control.system-ca-bundle
|
||||
Package Control.cache/
|
||||
Package Control.ca-certs/
|
||||
Package Control.merged-ca-bundle
|
||||
Package Control.user-ca-bundle
|
||||
oscrypto-ca-bundle.crt
|
||||
bh_unicode_properties.cache
|
||||
|
||||
# Sublime-github package stores a github token in this file
|
||||
# https://packagecontrol.io/packages/sublime-github
|
||||
GitHub.sublime-settings
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/linux,osx,macos,sublimetext,kate,kdevelop4,cmake,c,python
|
||||
|
||||
/include/cahute/config.h
|
||||
/CPack*
|
||||
/_CPack*
|
||||
/*.sh
|
||||
/*.tar.*
|
||||
/p7*
|
||||
/p7screen*
|
||||
/xfer9860*
|
||||
/.envrc
|
||||
/vgcore.*
|
||||
/misc/cahute.pc
|
|
@ -0,0 +1,73 @@
|
|||
stages:
|
||||
- lint
|
||||
- build
|
||||
- publish
|
||||
|
||||
pre-commit:
|
||||
stage: lint
|
||||
image: python:3.11
|
||||
before_script:
|
||||
- pip install pre-commit==3.6.0
|
||||
script:
|
||||
- pre-commit run -v --all-files
|
||||
|
||||
build (linux):
|
||||
stage: build
|
||||
image: debian:bookworm-slim
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
- apt-get install -y cmake pkg-config gcc libusb-1.0-0-dev libsdl2-dev
|
||||
script:
|
||||
- cmake -B build -S . -DCMAKE_INSTALL_PREFIX=/usr
|
||||
- cmake --build build
|
||||
|
||||
build docs:
|
||||
stage: build
|
||||
image: python:3.11
|
||||
before_script:
|
||||
- pip install -r docs/requirements.txt
|
||||
script:
|
||||
- sphinx-build -M html docs docs/_build
|
||||
artifacts:
|
||||
paths:
|
||||
- docs/_build/html
|
||||
|
||||
publish docs:
|
||||
stage: publish
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
when: always
|
||||
image: debian:bookworm-slim
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
- apt-get install -y rsync openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir ~/.ssh && chmod 700 ~/.ssh
|
||||
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >~/.ssh/config
|
||||
- chmod 400 "$SSH_PRIVATE_KEY"
|
||||
- ssh-add "$SSH_PRIVATE_KEY"
|
||||
script:
|
||||
- rsync -Prlt --delete docs/_build/html/ gitlab-cahute@cahuteproject.org:/var/www/cahuteproject/www
|
||||
dependencies:
|
||||
- build docs
|
||||
|
||||
publish tarball:
|
||||
stage: publish
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
when: always
|
||||
image: debian:bookworm-slim
|
||||
before_script:
|
||||
- apt-get update -y
|
||||
- apt-get install -y cmake pkg-config gcc libusb-1.0-0-dev libsdl2-dev openssh-client
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir ~/.ssh && chmod 700 ~/.ssh
|
||||
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >~/.ssh/config
|
||||
- chmod 400 "$SSH_PRIVATE_KEY"
|
||||
- ssh-add "$SSH_PRIVATE_KEY"
|
||||
script:
|
||||
- cmake -B build -S .
|
||||
- cpack --config build/CPackSourceConfig.cmake
|
||||
- export RELEASE_FILE=$(ls cahute-*.tar.gz)
|
||||
- sha256sum $RELEASE_FILE >$RELEASE_FILE.sha256
|
||||
- scp $RELEASE_FILE $RELEASE_FILE.sha256 gitlab-cahute@cahuteproject.org:/var/www/cahuteproject/ftp/releases
|
|
@ -0,0 +1,21 @@
|
|||
repos:
|
||||
- repo: https://github.com/commitizen-tools/commitizen
|
||||
rev: v2.38.0
|
||||
hooks:
|
||||
- id: commitizen
|
||||
stages: [commit-msg]
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: check-merge-conflict
|
||||
- id: check-ast
|
||||
- id: check-json
|
||||
- id: mixed-line-ending
|
||||
- id: end-of-file-fixer
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v17.0.6
|
||||
hooks:
|
||||
- id: clang-format
|
|
@ -0,0 +1 @@
|
|||
python 3.11.5
|
|
@ -0,0 +1,128 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(
|
||||
cahute
|
||||
VERSION 0.1
|
||||
DESCRIPTION "Communication and file format handling tools for CASIO calculators"
|
||||
HOMEPAGE_URL "https://cahuteproject.org/"
|
||||
LANGUAGES C
|
||||
)
|
||||
set(PROJECT_ISSUES_URL "https://cahuteproject.org/guides/report.html")
|
||||
|
||||
add_custom_target(lint COMMAND pre-commit run --all-files)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(
|
||||
CPACK_SOURCE_IGNORE_FILES
|
||||
"\\.git" "build/" ".*~$" "\\.envrc" "\\.pre-commit-config\\.yaml"
|
||||
"\\.clang-format" "__pycache__" "\\.gitlab-ci.yml" "_CPack"
|
||||
)
|
||||
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
|
||||
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
|
||||
set(CPACK_VERBATIM_VARIABLES true)
|
||||
include(CPack)
|
||||
|
||||
set(LOGLEVEL $ENV{LOGLEVEL})
|
||||
|
||||
if(NOT "${LOGLEVEL}" MATCHES "|none|info|warning|error|fatal")
|
||||
message(SEND_ERROR "LOGLEVEL should be one of [info, warning, error, fatal, none]")
|
||||
endif()
|
||||
|
||||
if(NOT LOGLEVEL)
|
||||
set(LOGLEVEL "fatal")
|
||||
endif()
|
||||
|
||||
string(TOUPPER ${LOGLEVEL} DEFAULT_LOGLEVEL)
|
||||
|
||||
execute_process(
|
||||
COMMAND printf "0x%02X%02X0000" ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR}
|
||||
OUTPUT_VARIABLE PROJECT_VERSION_HEX
|
||||
)
|
||||
|
||||
configure_file(include/cahute/config.h.in include/cahute/config.h ESCAPE_QUOTES)
|
||||
configure_file(misc/cahute.pc.in misc/cahute.pc ESCAPE_QUOTES @ONLY)
|
||||
|
||||
# ---
|
||||
# Build options.
|
||||
# ---
|
||||
|
||||
pkg_check_modules(libusb REQUIRED libusb-1.0 IMPORTED_TARGET)
|
||||
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
add_compile_options(
|
||||
-Wall -Wextra -Wno-unused-macros -Wno-vla
|
||||
-Wshadow -Wwrite-strings -Wredundant-decls -Wformat -Wformat-nonliteral
|
||||
-Wformat-security -Wimplicit-function-declaration
|
||||
-Wdate-time -Wmissing-prototypes -Wreturn-type -Wpointer-arith
|
||||
-Wstack-protector -Wno-unused-parameter
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC
|
||||
lib/cdefs.c
|
||||
lib/detection.c
|
||||
lib/link.c
|
||||
lib/logging.c
|
||||
lib/misc.c
|
||||
lib/seven.c
|
||||
lib/seven_ohp.c
|
||||
lib/stream.c
|
||||
)
|
||||
|
||||
add_executable(p7
|
||||
cli/p7.c
|
||||
cli/p7_args.c
|
||||
cli/common.c
|
||||
)
|
||||
|
||||
add_executable(p7screen
|
||||
cli/p7screen.c
|
||||
cli/p7screen_args.c
|
||||
cli/common.c
|
||||
)
|
||||
|
||||
add_executable(xfer9860
|
||||
cli/xfer9860.c
|
||||
cli/xfer9860_args.c
|
||||
cli/common.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${libusb_INCLUDE_DIRS}"
|
||||
)
|
||||
target_include_directories(p7screen PRIVATE ${SDL2_INCLUDE_DIR})
|
||||
|
||||
target_link_libraries(p7 PRIVATE ${PROJECT_NAME} PkgConfig::libusb)
|
||||
target_link_libraries(p7screen PRIVATE ${PROJECT_NAME} PkgConfig::libusb ${SDL2_LIBRARIES})
|
||||
target_link_libraries(xfer9860 PRIVATE ${PROJECT_NAME} PkgConfig::libusb)
|
||||
|
||||
# ---
|
||||
# Packaging options.
|
||||
# ---
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} ARCHIVE)
|
||||
install(TARGETS p7 RUNTIME)
|
||||
install(TARGETS p7screen RUNTIME)
|
||||
install(TARGETS xfer9860 RUNTIME)
|
||||
install(
|
||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" "${CMAKE_CURRENT_BINARY_DIR}/include/"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/misc/cahute.pc
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
||||
)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/misc/60-casio-calculators.rules
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/udev/rules.d"
|
||||
)
|
|
@ -0,0 +1,518 @@
|
|||
|
||||
CeCILL FREE SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
Version 2.1 dated 2013-06-21
|
||||
|
||||
|
||||
Notice
|
||||
|
||||
This Agreement is a Free Software license agreement that is the result
|
||||
of discussions between its authors in order to ensure compliance with
|
||||
the two main principles guiding its drafting:
|
||||
|
||||
* firstly, compliance with the principles governing the distribution
|
||||
of Free Software: access to source code, broad rights granted to users,
|
||||
* secondly, the election of a governing law, French law, with which it
|
||||
is conformant, both as regards the law of torts and intellectual
|
||||
property law, and the protection that it offers to both authors and
|
||||
holders of the economic rights over software.
|
||||
|
||||
The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
|
||||
license are:
|
||||
|
||||
Commissariat à l'énergie atomique et aux énergies alternatives - CEA, a
|
||||
public scientific, technical and industrial research establishment,
|
||||
having its principal place of business at 25 rue Leblanc, immeuble Le
|
||||
Ponant D, 75015 Paris, France.
|
||||
|
||||
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
||||
and technological establishment, having its principal place of business
|
||||
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
||||
|
||||
Institut National de Recherche en Informatique et en Automatique -
|
||||
Inria, a public scientific and technological establishment, having its
|
||||
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
||||
105, 78153 Le Chesnay cedex, France.
|
||||
|
||||
|
||||
Preamble
|
||||
|
||||
The purpose of this Free Software license agreement is to grant users
|
||||
the right to modify and redistribute the software governed by this
|
||||
license within the framework of an open source distribution model.
|
||||
|
||||
The exercising of this right is conditional upon certain obligations for
|
||||
users so as to preserve this status for all subsequent redistributions.
|
||||
|
||||
In consideration of access to the source code and the rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors only have limited liability.
|
||||
|
||||
In this respect, the risks associated with loading, using, modifying
|
||||
and/or developing or reproducing the software by the user are brought to
|
||||
the user's attention, given its Free Software status, which may make it
|
||||
complicated to use, with the result that its use is reserved for
|
||||
developers and experienced professionals having in-depth computer
|
||||
knowledge. Users are therefore encouraged to load and test the
|
||||
suitability of the software as regards their requirements in conditions
|
||||
enabling the security of their systems and/or data to be ensured and,
|
||||
more generally, to use and operate it in the same conditions of
|
||||
security. This Agreement may be freely reproduced and published,
|
||||
provided it is not altered, and that no provisions are either added or
|
||||
removed herefrom.
|
||||
|
||||
This Agreement may apply to any or all software for which the holder of
|
||||
the economic rights decides to submit the use thereof to its provisions.
|
||||
|
||||
Frequently asked questions can be found on the official website of the
|
||||
CeCILL licenses family (http://www.cecill.info/index.en.html) for any
|
||||
necessary clarification.
|
||||
|
||||
|
||||
Article 1 - DEFINITIONS
|
||||
|
||||
For the purpose of this Agreement, when the following expressions
|
||||
commence with a capital letter, they shall have the following meaning:
|
||||
|
||||
Agreement: means this license agreement, and its possible subsequent
|
||||
versions and annexes.
|
||||
|
||||
Software: means the software in its Object Code and/or Source Code form
|
||||
and, where applicable, its documentation, "as is" when the Licensee
|
||||
accepts the Agreement.
|
||||
|
||||
Initial Software: means the Software in its Source Code and possibly its
|
||||
Object Code form and, where applicable, its documentation, "as is" when
|
||||
it is first distributed under the terms and conditions of the Agreement.
|
||||
|
||||
Modified Software: means the Software modified by at least one
|
||||
Contribution.
|
||||
|
||||
Source Code: means all the Software's instructions and program lines to
|
||||
which access is required so as to modify the Software.
|
||||
|
||||
Object Code: means the binary files originating from the compilation of
|
||||
the Source Code.
|
||||
|
||||
Holder: means the holder(s) of the economic rights over the Initial
|
||||
Software.
|
||||
|
||||
Licensee: means the Software user(s) having accepted the Agreement.
|
||||
|
||||
Contributor: means a Licensee having made at least one Contribution.
|
||||
|
||||
Licensor: means the Holder, or any other individual or legal entity, who
|
||||
distributes the Software under the Agreement.
|
||||
|
||||
Contribution: means any or all modifications, corrections, translations,
|
||||
adaptations and/or new functions integrated into the Software by any or
|
||||
all Contributors, as well as any or all Internal Modules.
|
||||
|
||||
Module: means a set of sources files including their documentation that
|
||||
enables supplementary functions or services in addition to those offered
|
||||
by the Software.
|
||||
|
||||
External Module: means any or all Modules, not derived from the
|
||||
Software, so that this Module and the Software run in separate address
|
||||
spaces, with one calling the other when they are run.
|
||||
|
||||
Internal Module: means any or all Module, connected to the Software so
|
||||
that they both execute in the same address space.
|
||||
|
||||
GNU GPL: means the GNU General Public License version 2 or any
|
||||
subsequent version, as published by the Free Software Foundation Inc.
|
||||
|
||||
GNU Affero GPL: means the GNU Affero General Public License version 3 or
|
||||
any subsequent version, as published by the Free Software Foundation Inc.
|
||||
|
||||
EUPL: means the European Union Public License version 1.1 or any
|
||||
subsequent version, as published by the European Commission.
|
||||
|
||||
Parties: mean both the Licensee and the Licensor.
|
||||
|
||||
These expressions may be used both in singular and plural form.
|
||||
|
||||
|
||||
Article 2 - PURPOSE
|
||||
|
||||
The purpose of the Agreement is the grant by the Licensor to the
|
||||
Licensee of a non-exclusive, transferable and worldwide license for the
|
||||
Software as set forth in Article 5 <#scope> hereinafter for the whole
|
||||
term of the protection granted by the rights over said Software.
|
||||
|
||||
|
||||
Article 3 - ACCEPTANCE
|
||||
|
||||
3.1 The Licensee shall be deemed as having accepted the terms and
|
||||
conditions of this Agreement upon the occurrence of the first of the
|
||||
following events:
|
||||
|
||||
* (i) loading the Software by any or all means, notably, by
|
||||
downloading from a remote server, or by loading from a physical medium;
|
||||
* (ii) the first time the Licensee exercises any of the rights granted
|
||||
hereunder.
|
||||
|
||||
3.2 One copy of the Agreement, containing a notice relating to the
|
||||
characteristics of the Software, to the limited warranty, and to the
|
||||
fact that its use is restricted to experienced users has been provided
|
||||
to the Licensee prior to its acceptance as set forth in Article 3.1
|
||||
<#accepting> hereinabove, and the Licensee hereby acknowledges that it
|
||||
has read and understood it.
|
||||
|
||||
|
||||
Article 4 - EFFECTIVE DATE AND TERM
|
||||
|
||||
|
||||
4.1 EFFECTIVE DATE
|
||||
|
||||
The Agreement shall become effective on the date when it is accepted by
|
||||
the Licensee as set forth in Article 3.1 <#accepting>.
|
||||
|
||||
|
||||
4.2 TERM
|
||||
|
||||
The Agreement shall remain in force for the entire legal term of
|
||||
protection of the economic rights over the Software.
|
||||
|
||||
|
||||
Article 5 - SCOPE OF RIGHTS GRANTED
|
||||
|
||||
The Licensor hereby grants to the Licensee, who accepts, the following
|
||||
rights over the Software for any or all use, and for the term of the
|
||||
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
||||
|
||||
Besides, if the Licensor owns or comes to own one or more patents
|
||||
protecting all or part of the functions of the Software or of its
|
||||
components, the Licensor undertakes not to enforce the rights granted by
|
||||
these patents against successive Licensees using, exploiting or
|
||||
modifying the Software. If these patents are transferred, the Licensor
|
||||
undertakes to have the transferees subscribe to the obligations set
|
||||
forth in this paragraph.
|
||||
|
||||
|
||||
5.1 RIGHT OF USE
|
||||
|
||||
The Licensee is authorized to use the Software, without any limitation
|
||||
as to its fields of application, with it being hereinafter specified
|
||||
that this comprises:
|
||||
|
||||
1. permanent or temporary reproduction of all or part of the Software
|
||||
by any or all means and in any or all form.
|
||||
|
||||
2. loading, displaying, running, or storing the Software on any or all
|
||||
medium.
|
||||
|
||||
3. entitlement to observe, study or test its operation so as to
|
||||
determine the ideas and principles behind any or all constituent
|
||||
elements of said Software. This shall apply when the Licensee
|
||||
carries out any or all loading, displaying, running, transmission or
|
||||
storage operation as regards the Software, that it is entitled to
|
||||
carry out hereunder.
|
||||
|
||||
|
||||
5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
|
||||
|
||||
The right to make Contributions includes the right to translate, adapt,
|
||||
arrange, or make any or all modifications to the Software, and the right
|
||||
to reproduce the resulting software.
|
||||
|
||||
The Licensee is authorized to make any or all Contributions to the
|
||||
Software provided that it includes an explicit notice that it is the
|
||||
author of said Contribution and indicates the date of the creation thereof.
|
||||
|
||||
|
||||
5.3 RIGHT OF DISTRIBUTION
|
||||
|
||||
In particular, the right of distribution includes the right to publish,
|
||||
transmit and communicate the Software to the general public on any or
|
||||
all medium, and by any or all means, and the right to market, either in
|
||||
consideration of a fee, or free of charge, one or more copies of the
|
||||
Software by any means.
|
||||
|
||||
The Licensee is further authorized to distribute copies of the modified
|
||||
or unmodified Software to third parties according to the terms and
|
||||
conditions set forth hereinafter.
|
||||
|
||||
|
||||
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
||||
|
||||
The Licensee is authorized to distribute true copies of the Software in
|
||||
Source Code or Object Code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's warranty
|
||||
and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and that, in the event that only the Object Code of the Software is
|
||||
redistributed, the Licensee allows effective access to the full Source
|
||||
Code of the Software for a period of at least three years from the
|
||||
distribution of the Software, it being understood that the additional
|
||||
acquisition cost of the Source Code shall not exceed the cost of the
|
||||
data transfer.
|
||||
|
||||
|
||||
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
||||
|
||||
When the Licensee makes a Contribution to the Software, the terms and
|
||||
conditions for the distribution of the resulting Modified Software
|
||||
become subject to all the provisions of this Agreement.
|
||||
|
||||
The Licensee is authorized to distribute the Modified Software, in
|
||||
source code or object code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's warranty
|
||||
and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and, in the event that only the object code of the Modified Software is
|
||||
redistributed,
|
||||
|
||||
3. a note stating the conditions of effective access to the full source
|
||||
code of the Modified Software for a period of at least three years
|
||||
from the distribution of the Modified Software, it being understood
|
||||
that the additional acquisition cost of the source code shall not
|
||||
exceed the cost of the data transfer.
|
||||
|
||||
|
||||
5.3.3 DISTRIBUTION OF EXTERNAL MODULES
|
||||
|
||||
When the Licensee has developed an External Module, the terms and
|
||||
conditions of this Agreement do not apply to said External Module, that
|
||||
may be distributed under a separate license agreement.
|
||||
|
||||
|
||||
5.3.4 COMPATIBILITY WITH OTHER LICENSES
|
||||
|
||||
The Licensee can include a code that is subject to the provisions of one
|
||||
of the versions of the GNU GPL, GNU Affero GPL and/or EUPL in the
|
||||
Modified or unmodified Software, and distribute that entire code under
|
||||
the terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
|
||||
|
||||
The Licensee can include the Modified or unmodified Software in a code
|
||||
that is subject to the provisions of one of the versions of the GNU GPL,
|
||||
GNU Affero GPL and/or EUPL and distribute that entire code under the
|
||||
terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
|
||||
|
||||
|
||||
Article 6 - INTELLECTUAL PROPERTY
|
||||
|
||||
|
||||
6.1 OVER THE INITIAL SOFTWARE
|
||||
|
||||
The Holder owns the economic rights over the Initial Software. Any or
|
||||
all use of the Initial Software is subject to compliance with the terms
|
||||
and conditions under which the Holder has elected to distribute its work
|
||||
and no one shall be entitled to modify the terms and conditions for the
|
||||
distribution of said Initial Software.
|
||||
|
||||
The Holder undertakes that the Initial Software will remain ruled at
|
||||
least by this Agreement, for the duration set forth in Article 4.2 <#term>.
|
||||
|
||||
|
||||
6.2 OVER THE CONTRIBUTIONS
|
||||
|
||||
The Licensee who develops a Contribution is the owner of the
|
||||
intellectual property rights over this Contribution as defined by
|
||||
applicable law.
|
||||
|
||||
|
||||
6.3 OVER THE EXTERNAL MODULES
|
||||
|
||||
The Licensee who develops an External Module is the owner of the
|
||||
intellectual property rights over this External Module as defined by
|
||||
applicable law and is free to choose the type of agreement that shall
|
||||
govern its distribution.
|
||||
|
||||
|
||||
6.4 JOINT PROVISIONS
|
||||
|
||||
The Licensee expressly undertakes:
|
||||
|
||||
1. not to remove, or modify, in any manner, the intellectual property
|
||||
notices attached to the Software;
|
||||
|
||||
2. to reproduce said notices, in an identical manner, in the copies of
|
||||
the Software modified or not.
|
||||
|
||||
The Licensee undertakes not to directly or indirectly infringe the
|
||||
intellectual property rights on the Software of the Holder and/or
|
||||
Contributors, and to take, where applicable, vis-à-vis its staff, any
|
||||
and all measures required to ensure respect of said intellectual
|
||||
property rights of the Holder and/or Contributors.
|
||||
|
||||
|
||||
Article 7 - RELATED SERVICES
|
||||
|
||||
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
||||
provide technical assistance or maintenance services for the Software.
|
||||
|
||||
However, the Licensor is entitled to offer this type of services. The
|
||||
terms and conditions of such technical assistance, and/or such
|
||||
maintenance, shall be set forth in a separate instrument. Only the
|
||||
Licensor offering said maintenance and/or technical assistance services
|
||||
shall incur liability therefor.
|
||||
|
||||
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
||||
its sole responsibility, a warranty, that shall only be binding upon
|
||||
itself, for the redistribution of the Software and/or the Modified
|
||||
Software, under terms and conditions that it is free to decide. Said
|
||||
warranty, and the financial terms and conditions of its application,
|
||||
shall be subject of a separate instrument executed between the Licensor
|
||||
and the Licensee.
|
||||
|
||||
|
||||
Article 8 - LIABILITY
|
||||
|
||||
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
||||
entitled to claim compensation for any direct loss it may have suffered
|
||||
from the Software as a result of a fault on the part of the relevant
|
||||
Licensor, subject to providing evidence thereof.
|
||||
|
||||
8.2 The Licensor's liability is limited to the commitments made under
|
||||
this Agreement and shall not be incurred as a result of in particular:
|
||||
(i) loss due the Licensee's total or partial failure to fulfill its
|
||||
obligations, (ii) direct or consequential loss that is suffered by the
|
||||
Licensee due to the use or performance of the Software, and (iii) more
|
||||
generally, any consequential loss. In particular the Parties expressly
|
||||
agree that any or all pecuniary or business loss (i.e. loss of data,
|
||||
loss of profits, operating loss, loss of customers or orders,
|
||||
opportunity cost, any disturbance to business activities) or any or all
|
||||
legal proceedings instituted against the Licensee by a third party,
|
||||
shall constitute consequential loss and shall not provide entitlement to
|
||||
any or all compensation from the Licensor.
|
||||
|
||||
|
||||
Article 9 - WARRANTY
|
||||
|
||||
9.1 The Licensee acknowledges that the scientific and technical
|
||||
state-of-the-art when the Software was distributed did not enable all
|
||||
possible uses to be tested and verified, nor for the presence of
|
||||
possible defects to be detected. In this respect, the Licensee's
|
||||
attention has been drawn to the risks associated with loading, using,
|
||||
modifying and/or developing and reproducing the Software which are
|
||||
reserved for experienced users.
|
||||
|
||||
The Licensee shall be responsible for verifying, by any or all means,
|
||||
the suitability of the product for its requirements, its good working
|
||||
order, and for ensuring that it shall not cause damage to either persons
|
||||
or properties.
|
||||
|
||||
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
||||
to grant all the rights over the Software (including in particular the
|
||||
rights set forth in Article 5 <#scope>).
|
||||
|
||||
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
||||
the Licensor without any other express or tacit warranty, other than
|
||||
that provided for in Article 9.2 <#good-faith> and, in particular,
|
||||
without any warranty as to its commercial value, its secured, safe,
|
||||
innovative or relevant nature.
|
||||
|
||||
Specifically, the Licensor does not warrant that the Software is free
|
||||
from any error, that it will operate without interruption, that it will
|
||||
be compatible with the Licensee's own equipment and software
|
||||
configuration, nor that it will meet the Licensee's requirements.
|
||||
|
||||
9.4 The Licensor does not either expressly or tacitly warrant that the
|
||||
Software does not infringe any third party intellectual property right
|
||||
relating to a patent, software or any other property right. Therefore,
|
||||
the Licensor disclaims any and all liability towards the Licensee
|
||||
arising out of any or all proceedings for infringement that may be
|
||||
instituted in respect of the use, modification and redistribution of the
|
||||
Software. Nevertheless, should such proceedings be instituted against
|
||||
the Licensee, the Licensor shall provide it with technical and legal
|
||||
expertise for its defense. Such technical and legal expertise shall be
|
||||
decided on a case-by-case basis between the relevant Licensor and the
|
||||
Licensee pursuant to a memorandum of understanding. The Licensor
|
||||
disclaims any and all liability as regards the Licensee's use of the
|
||||
name of the Software. No warranty is given as regards the existence of
|
||||
prior rights over the name of the Software or as regards the existence
|
||||
of a trademark.
|
||||
|
||||
|
||||
Article 10 - TERMINATION
|
||||
|
||||
10.1 In the event of a breach by the Licensee of its obligations
|
||||
hereunder, the Licensor may automatically terminate this Agreement
|
||||
thirty (30) days after notice has been sent to the Licensee and has
|
||||
remained ineffective.
|
||||
|
||||
10.2 A Licensee whose Agreement is terminated shall no longer be
|
||||
authorized to use, modify or distribute the Software. However, any
|
||||
licenses that it may have granted prior to termination of the Agreement
|
||||
shall remain valid subject to their having been granted in compliance
|
||||
with the terms and conditions hereof.
|
||||
|
||||
|
||||
Article 11 - MISCELLANEOUS
|
||||
|
||||
|
||||
11.1 EXCUSABLE EVENTS
|
||||
|
||||
Neither Party shall be liable for any or all delay, or failure to
|
||||
perform the Agreement, that may be attributable to an event of force
|
||||
majeure, an act of God or an outside cause, such as defective
|
||||
functioning or interruptions of the electricity or telecommunications
|
||||
networks, network paralysis following a virus attack, intervention by
|
||||
government authorities, natural disasters, water damage, earthquakes,
|
||||
fire, explosions, strikes and labor unrest, war, etc.
|
||||
|
||||
11.2 Any failure by either Party, on one or more occasions, to invoke
|
||||
one or more of the provisions hereof, shall under no circumstances be
|
||||
interpreted as being a waiver by the interested Party of its right to
|
||||
invoke said provision(s) subsequently.
|
||||
|
||||
11.3 The Agreement cancels and replaces any or all previous agreements,
|
||||
whether written or oral, between the Parties and having the same
|
||||
purpose, and constitutes the entirety of the agreement between said
|
||||
Parties concerning said purpose. No supplement or modification to the
|
||||
terms and conditions hereof shall be effective as between the Parties
|
||||
unless it is made in writing and signed by their duly authorized
|
||||
representatives.
|
||||
|
||||
11.4 In the event that one or more of the provisions hereof were to
|
||||
conflict with a current or future applicable act or legislative text,
|
||||
said act or legislative text shall prevail, and the Parties shall make
|
||||
the necessary amendments so as to comply with said act or legislative
|
||||
text. All other provisions shall remain effective. Similarly, invalidity
|
||||
of a provision of the Agreement, for any reason whatsoever, shall not
|
||||
cause the Agreement as a whole to be invalid.
|
||||
|
||||
|
||||
11.5 LANGUAGE
|
||||
|
||||
The Agreement is drafted in both French and English and both versions
|
||||
are deemed authentic.
|
||||
|
||||
|
||||
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
||||
|
||||
12.1 Any person is authorized to duplicate and distribute copies of this
|
||||
Agreement.
|
||||
|
||||
12.2 So as to ensure coherence, the wording of this Agreement is
|
||||
protected and may only be modified by the authors of the License, who
|
||||
reserve the right to periodically publish updates or new versions of the
|
||||
Agreement, each with a separate number. These subsequent versions may
|
||||
address new issues encountered by Free Software.
|
||||
|
||||
12.3 Any Software distributed under a given version of the Agreement may
|
||||
only be subsequently distributed under the same version of the Agreement
|
||||
or a subsequent version, subject to the provisions of Article 5.3.4
|
||||
<#compatibility>.
|
||||
|
||||
|
||||
Article 13 - GOVERNING LAW AND JURISDICTION
|
||||
|
||||
13.1 The Agreement is governed by French law. The Parties agree to
|
||||
endeavor to seek an amicable solution to any disagreements or disputes
|
||||
that may arise during the performance of the Agreement.
|
||||
|
||||
13.2 Failing an amicable solution within two (2) months as from their
|
||||
occurrence, and unless emergency proceedings are necessary, the
|
||||
disagreements or disputes shall be referred to the Paris Courts having
|
||||
jurisdiction, by the more diligent Party.
|
|
@ -0,0 +1,19 @@
|
|||
Cahute -- Communication and file format handling tools for CASIO calculators
|
||||
============================================================================
|
||||
|
||||
Cahute is a library and set of command-line utilities to handle serial
|
||||
and USB communication protocols and file formats related to CASIO calculators,
|
||||
dating from the 1990s to today.
|
||||
|
||||
For more information, consult the following links:
|
||||
|
||||
* `Cahute documentation`_, for more information on the project and its context;
|
||||
* `Issue tracker`_, and the `issue reporting guide`_;
|
||||
* `Pending contributions`_, and the related `contributing guide`_.
|
||||
|
||||
.. _Cahute documentation: https://cahuteproject.org/
|
||||
.. _Issue tracker: https://gitlab.com/cahuteproject/cahute/-/issues
|
||||
.. _Issue reporting guide: https://cahuteproject.org/guides/report.html
|
||||
.. _Pending contributions:
|
||||
https://gitlab.com/cahuteproject/cahute/-/merge_requests
|
||||
.. _Contributing guide: https://cahuteproject.org/guides/contribute.html
|
|
@ -0,0 +1,174 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "common.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Cookie for the USB finder.
|
||||
*
|
||||
* @property should_display Whether the program should display the options
|
||||
* if multiple are found.
|
||||
* @property multiple Boolean set to 1 if multiple devices were already
|
||||
* detected.
|
||||
* @property last_bus Bus of the last found device, -1 if uninitialized.
|
||||
* @property last_address Address of the last found device, -1 if
|
||||
* uninitialized.
|
||||
* @property last_type Type of the last found device, -1 if uninitialized.
|
||||
*/
|
||||
struct usb_device_finder_cookie {
|
||||
int should_display;
|
||||
int multiple;
|
||||
int last_bus;
|
||||
int last_address;
|
||||
int last_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* USB finder callback.
|
||||
*
|
||||
* @param cookie Cookie of the USB device finder.
|
||||
*/
|
||||
static int find_usb_device(
|
||||
struct usb_device_finder_cookie *cookie,
|
||||
cahute_usb_detection_entry const *entry
|
||||
) {
|
||||
if (cookie->last_bus >= 0) {
|
||||
if (!cookie->multiple && cookie->should_display) {
|
||||
fprintf(stderr, "Multiple USB calculators were found:\n");
|
||||
fprintf(
|
||||
stderr,
|
||||
" Bus %03d Device %03d: %s\n",
|
||||
cookie->last_bus,
|
||||
cookie->last_address,
|
||||
cookie->last_type == CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN
|
||||
? "fx-9860G compatible calculator (Protocol 7.00)"
|
||||
: "fx-CG compatible calculator (SCSI)"
|
||||
);
|
||||
}
|
||||
|
||||
cookie->multiple = 1;
|
||||
if (cookie->should_display) {
|
||||
fprintf(
|
||||
stderr,
|
||||
" Bus %03d Device %03d: %s\n",
|
||||
entry->cahute_usb_detection_entry_bus,
|
||||
entry->cahute_usb_detection_entry_address,
|
||||
entry->cahute_usb_detection_entry_type
|
||||
== CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN
|
||||
? "fx-9860G compatible calculator (Protocol 7.00)"
|
||||
: "fx-CG compatible calculator (SCSI)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cookie->last_bus = entry->cahute_usb_detection_entry_bus;
|
||||
cookie->last_address = entry->cahute_usb_detection_entry_address;
|
||||
cookie->last_type = entry->cahute_usb_detection_entry_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find out the USB bus and address of the only USB device.
|
||||
*
|
||||
* @param should_display Whether the program should display the options, if
|
||||
* multiple are present.
|
||||
* @param busp Pointer to the bus to define.
|
||||
* @param addressp Pointer to the address to define.
|
||||
* @return Cahute error (> 0), -1 if multiple devices were found, or 0 if ok.
|
||||
*/
|
||||
extern int find_usb_calculator(int should_display, int *busp, int *addressp) {
|
||||
struct usb_device_finder_cookie cookie;
|
||||
int err;
|
||||
|
||||
cookie.should_display = should_display;
|
||||
cookie.last_bus = -1;
|
||||
cookie.last_address = -1;
|
||||
cookie.last_type = -1;
|
||||
cookie.multiple = 0;
|
||||
|
||||
err = cahute_detect_usb(
|
||||
(cahute_detect_usb_entry_func *)find_usb_device,
|
||||
&cookie
|
||||
);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (cookie.last_bus < 0)
|
||||
return CAHUTE_ERROR_NOT_FOUND;
|
||||
if (cookie.multiple)
|
||||
return CAHUTE_ERROR_TOO_MANY;
|
||||
|
||||
*busp = cookie.last_bus;
|
||||
*addressp = cookie.last_address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current logging level as a string.
|
||||
*
|
||||
* @return Logging level name.
|
||||
*/
|
||||
extern char const *get_current_log_level(void) {
|
||||
int loglevel = cahute_get_log_level();
|
||||
|
||||
switch (loglevel) {
|
||||
case CAHUTE_LOGLEVEL_INFO:
|
||||
return "info";
|
||||
case CAHUTE_LOGLEVEL_WARNING:
|
||||
return "warning";
|
||||
case CAHUTE_LOGLEVEL_ERROR:
|
||||
return "error";
|
||||
case CAHUTE_LOGLEVEL_FATAL:
|
||||
return "fatal";
|
||||
default:
|
||||
return "(none)";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current logging level as a string.
|
||||
*
|
||||
* @param loglevel Name of the loglevel to set.
|
||||
*/
|
||||
extern void set_log_level(char const *loglevel) {
|
||||
int value = CAHUTE_LOGLEVEL_NONE;
|
||||
|
||||
if (!strcmp(loglevel, "info"))
|
||||
value = CAHUTE_LOGLEVEL_INFO;
|
||||
else if (!strcmp(loglevel, "warning"))
|
||||
value = CAHUTE_LOGLEVEL_WARNING;
|
||||
else if (!strcmp(loglevel, "error"))
|
||||
value = CAHUTE_LOGLEVEL_ERROR;
|
||||
else if (!strcmp(loglevel, "fatal"))
|
||||
value = CAHUTE_LOGLEVEL_FATAL;
|
||||
|
||||
cahute_set_log_level(value);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H 1
|
||||
#include <cahute.h>
|
||||
|
||||
extern int find_usb_calculator(int should_display, int *busp, int *addressp);
|
||||
|
||||
extern char const *get_current_log_level(void);
|
||||
extern void set_log_level(char const *loglevel);
|
||||
|
||||
#endif /* COMMON_H */
|
|
@ -0,0 +1,509 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "p7.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* The operation was not implemented (yet). */
|
||||
static char const error_notimplemented[] =
|
||||
"The requested operation was not implemented yet.\n";
|
||||
|
||||
/* Couldn't initialize connexion with the calculator. */
|
||||
static char const error_notfound[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in receive mode?\n"
|
||||
"- Have you tried changing the cable?\n";
|
||||
|
||||
/* Calculator was disconnected. */
|
||||
static char const error_disconnected[] =
|
||||
"Lost connexion to the calculator!\n"
|
||||
"Please reconnect the calculator, rerun receive mode and try again.\n";
|
||||
|
||||
/* Calculator was found but program wasn't allowed to communicate with it. */
|
||||
static char const error_noaccess[] =
|
||||
"Could not get access to the calculator.\n"
|
||||
"Install the appropriate udev rule, or run as root.\n";
|
||||
|
||||
/* Command was unsupported. */
|
||||
static char const error_unsupported[] =
|
||||
"The command is unsupported by the calculator.\n"
|
||||
"- Does the calculator have mass storage?\n"
|
||||
"- Does its OS allow the use of it?\n"
|
||||
"- Is it in Receive Mode (and not in OS Update)?\n";
|
||||
|
||||
/* The calculator acted in an unplanned way. */
|
||||
static char const error_unplanned[] =
|
||||
"The calculator didn't act as planned.\n"
|
||||
"Stop receive mode on calculator and start it again before "
|
||||
"re-running %s.\n";
|
||||
|
||||
/**
|
||||
* Print a serial device.
|
||||
*
|
||||
* @param firstp Whether the first entry has already been printed or not,
|
||||
* as a cookie.
|
||||
* @param entry Entry to display.
|
||||
*/
|
||||
static int
|
||||
print_serial_device(int *firstp, cahute_serial_detection_entry const *entry) {
|
||||
if (!*firstp) {
|
||||
printf("Available devices:\n\n");
|
||||
*firstp = 1;
|
||||
}
|
||||
|
||||
printf("- %s\n", entry->cahute_serial_detection_entry_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a storage entry for file and directory listing.
|
||||
*
|
||||
* @param cookie (unused)
|
||||
* @param entry Entry.
|
||||
* @return 0, so that the file listing goes to the end.
|
||||
*/
|
||||
static int
|
||||
print_storage_entry(void *cookie, cahute_storage_entry const *entry) {
|
||||
char const *directory = entry->cahute_storage_entry_directory;
|
||||
char const *name = entry->cahute_storage_entry_name;
|
||||
char formatted_name[30];
|
||||
|
||||
(void)cookie;
|
||||
snprintf(
|
||||
formatted_name,
|
||||
28,
|
||||
"%s%s%s",
|
||||
directory ? directory : "",
|
||||
directory ? "/" : "",
|
||||
name ? name : ""
|
||||
);
|
||||
printf(
|
||||
"%-27.27s %10luo\n",
|
||||
formatted_name,
|
||||
entry->cahute_storage_entry_size
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display progress.
|
||||
*
|
||||
* @param initp Pointer to an integer (as a cookie) to set to 1 if the
|
||||
* function has been called.
|
||||
* @param step Index of the latest accomplished step.
|
||||
* @param total Total number of steps to accomplish.
|
||||
*/
|
||||
static void
|
||||
display_progress(int *initp, unsigned long step, unsigned long total) {
|
||||
char buf[50];
|
||||
unsigned long i, percent = 10000 * step / total;
|
||||
|
||||
*initp = 1;
|
||||
sprintf(
|
||||
buf,
|
||||
"\r|---------------------------------------| %02lu.%02lu%%",
|
||||
(percent / 100) % 100,
|
||||
percent % 100
|
||||
);
|
||||
|
||||
for (i = 39 * step / total; i--;)
|
||||
buf[2 + i] = '#';
|
||||
|
||||
fputs(buf, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request user confirmation for an overwrite interactively.
|
||||
*
|
||||
* @param cookie (unused)
|
||||
* @return 1 if the overwrite is confirmed, 0 otherwise.
|
||||
*/
|
||||
static int confirm_overwrite(void *cookie) {
|
||||
char line[12];
|
||||
|
||||
(void)cookie;
|
||||
|
||||
printf("It looks like the file already exists on the calculator.\n");
|
||||
printf("Overwrite? ([n]/y) ");
|
||||
|
||||
if (!fgets(line, 10, stdin))
|
||||
return 0;
|
||||
|
||||
return line[0] == 'y' || line[0] == 'Y';
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a link depending on the parsed command-line.
|
||||
*
|
||||
* This function also takes care of changing the serial attributes, if the
|
||||
* opened link is on a serial medium.
|
||||
*
|
||||
* @param linkp Pointer to the link to initialize.
|
||||
* @param args Parsed parameters to base ourselves on.
|
||||
* @return Cahute error, or CAHUTE_OK if everything is ok.
|
||||
*/
|
||||
static int open_link(cahute_link **linkp, struct args const *args) {
|
||||
cahute_link *link = NULL;
|
||||
int bus, address, err;
|
||||
unsigned long flags;
|
||||
|
||||
if (args->serial_name) {
|
||||
/* The user has selected a serial stream! */
|
||||
flags = args->serial_flags | CAHUTE_SERIAL_PROTOCOL_SEVEN;
|
||||
if (args->no_init)
|
||||
flags |= CAHUTE_SERIAL_NOCHECK;
|
||||
if (args->no_term)
|
||||
flags |= CAHUTE_SERIAL_NOTERM;
|
||||
|
||||
err = cahute_open_serial_link(
|
||||
&link,
|
||||
flags,
|
||||
args->serial_name,
|
||||
args->serial_speed
|
||||
);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (args->change_serial) {
|
||||
/* We want to change the serial settings as part of the
|
||||
* opening procedure. If this fails, we need to actually close
|
||||
* the link. */
|
||||
err = cahute_negotiate_serial_params(
|
||||
link,
|
||||
args->new_serial_flags,
|
||||
args->new_serial_speed
|
||||
);
|
||||
if (err) {
|
||||
cahute_close_link(link);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
*linkp = link;
|
||||
return 0;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
if (args->no_init)
|
||||
flags |= CAHUTE_USB_NOCHECK;
|
||||
if (args->no_term)
|
||||
flags |= CAHUTE_USB_NOTERM;
|
||||
|
||||
if ((err = find_usb_calculator(1, &bus, &address)))
|
||||
return err;
|
||||
if ((err = cahute_open_usb_link(&link, flags, bus, address)))
|
||||
return err;
|
||||
|
||||
*linkp = link;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display device information.
|
||||
*
|
||||
* @param link Link to use to obtain the information.
|
||||
* @return Cahute error.
|
||||
*/
|
||||
static int print_device_info(cahute_link *link) {
|
||||
cahute_device_info *info;
|
||||
int err;
|
||||
|
||||
if ((err = cahute_get_device_info(link, &info)))
|
||||
return err;
|
||||
|
||||
/* Wiped out things */
|
||||
if (~info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_PREPROG)
|
||||
fprintf(
|
||||
stderr,
|
||||
"Warning: Preprogrammed ROM information looks wiped out!\n"
|
||||
);
|
||||
if (~info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_BOOTCODE)
|
||||
fprintf(stderr, "Warning: Bootcode information looks wiped out!\n");
|
||||
if (~info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_OS)
|
||||
fprintf(stderr, "Warning: OS information looks wiped out!\n");
|
||||
if (!info->cahute_device_info_username[0])
|
||||
fprintf(stderr, "Warning: Username is not set.\n");
|
||||
|
||||
printf(
|
||||
"CPU ID (probably out of date): %s\n",
|
||||
info->cahute_device_info_cpuid
|
||||
);
|
||||
printf("Environnement ID: %s\n", info->cahute_device_info_hwid);
|
||||
printf("Product ID: %s\n", info->cahute_device_info_product_id);
|
||||
|
||||
/* Preprogrammed ROM */
|
||||
if (info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_PREPROG) {
|
||||
printf(
|
||||
"Preprogrammed ROM version: %02u.%02u",
|
||||
info->cahute_device_info_rom_version.cahute_version_major,
|
||||
info->cahute_device_info_rom_version.cahute_version_minor
|
||||
);
|
||||
printf(
|
||||
"\nPreprogrammed ROM capacity: %luKiB\n",
|
||||
info->cahute_device_info_rom_capacity / 1024
|
||||
);
|
||||
}
|
||||
|
||||
/* ROM and RAM */
|
||||
printf(
|
||||
"ROM capacity: %luKiB\n",
|
||||
info->cahute_device_info_flash_rom_capacity / 1024
|
||||
);
|
||||
printf(
|
||||
"RAM capacity: %luKiB\n",
|
||||
info->cahute_device_info_ram_capacity / 1024
|
||||
);
|
||||
|
||||
/* Bootcode */
|
||||
if (info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_BOOTCODE) {
|
||||
printf(
|
||||
"Bootcode version: %02u.%02u",
|
||||
info->cahute_device_info_bootcode_version.cahute_version_major,
|
||||
info->cahute_device_info_bootcode_version.cahute_version_minor
|
||||
);
|
||||
printf(
|
||||
"\nBootcode offset: 0x%08lX\n",
|
||||
info->cahute_device_info_bootcode_offset
|
||||
);
|
||||
printf(
|
||||
"Bootcode size: %luB\n",
|
||||
info->cahute_device_info_bootcode_size
|
||||
);
|
||||
}
|
||||
|
||||
/* OS */
|
||||
if (info->cahute_device_info_flags & CAHUTE_DEVICE_INFO_FLAG_OS) {
|
||||
printf(
|
||||
"OS version: %02d.%02d.%d%d%d%d",
|
||||
info->cahute_device_info_os_version.cahute_version_major,
|
||||
info->cahute_device_info_os_version.cahute_version_minor,
|
||||
info->cahute_device_info_os_version.cahute_version_zone,
|
||||
info->cahute_device_info_os_version.cahute_version_math,
|
||||
info->cahute_device_info_os_version.cahute_version_status,
|
||||
info->cahute_device_info_os_version.cahute_version_platform
|
||||
);
|
||||
printf("\nOS offset: 0x%08lX\n", info->cahute_device_info_os_offset);
|
||||
printf("OS size: %luB\n", info->cahute_device_info_os_size);
|
||||
}
|
||||
|
||||
/* Miscallenous information */
|
||||
if (info->cahute_device_info_username[0])
|
||||
printf("Username: %s\n", info->cahute_device_info_username);
|
||||
if (info->cahute_device_info_organisation[0])
|
||||
printf("Organisation: %s\n", info->cahute_device_info_organisation);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function.
|
||||
*
|
||||
* @param ac Argument count.
|
||||
* @param av Argument values.
|
||||
*/
|
||||
int main(int ac, char **av) {
|
||||
cahute_link *link = NULL;
|
||||
struct args args;
|
||||
unsigned long flags;
|
||||
int err, progress_displayed = 0;
|
||||
|
||||
if (!parse_args(ac, av, &args))
|
||||
return 0;
|
||||
|
||||
if (args.command == COMMAND_LIST_SERIAL) {
|
||||
/* The "list-devices" command does not require a link, and as such,
|
||||
* is processed here independently from the others. */
|
||||
int first = 0;
|
||||
|
||||
err = cahute_detect_serial(
|
||||
(cahute_detect_serial_entry_func *)print_serial_device,
|
||||
&first
|
||||
);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
if (!first)
|
||||
fprintf(stderr, "Could not find any devices.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the link using the provided args. */
|
||||
err = open_link(&link, &args);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
switch (args.command) {
|
||||
case COMMAND_INFO:
|
||||
err = print_device_info(link);
|
||||
break;
|
||||
|
||||
case COMMAND_IDLE:
|
||||
/* Nothing to do! */
|
||||
break;
|
||||
|
||||
case COMMAND_SEND:
|
||||
flags = CAHUTE_SEND_FILE_FLAG_OPTIMIZE;
|
||||
if (args.force)
|
||||
flags |= CAHUTE_SEND_FILE_FLAG_FORCE;
|
||||
|
||||
err = cahute_send_file_to_storage(
|
||||
link,
|
||||
flags,
|
||||
args.distant_target_directory_name,
|
||||
args.distant_target_name,
|
||||
args.storage_name,
|
||||
args.local_source_fp,
|
||||
&confirm_overwrite,
|
||||
NULL,
|
||||
args.nice_display ? (cahute_progress_func *)&display_progress : 0,
|
||||
&progress_displayed
|
||||
);
|
||||
break;
|
||||
|
||||
case COMMAND_GET:
|
||||
err = cahute_request_file_from_storage(
|
||||
link,
|
||||
args.distant_source_directory_name,
|
||||
args.distant_source_name,
|
||||
args.storage_name,
|
||||
args.local_target_fp,
|
||||
args.nice_display ? (cahute_progress_func *)&display_progress : 0,
|
||||
&progress_displayed
|
||||
);
|
||||
break;
|
||||
|
||||
case COMMAND_COPY:
|
||||
err = cahute_copy_file_on_storage(
|
||||
link,
|
||||
args.distant_source_directory_name,
|
||||
args.distant_source_name,
|
||||
args.distant_target_directory_name,
|
||||
args.distant_target_name,
|
||||
args.storage_name
|
||||
);
|
||||
break;
|
||||
|
||||
case COMMAND_DELETE:
|
||||
err = cahute_delete_file_from_storage(
|
||||
link,
|
||||
args.distant_target_directory_name,
|
||||
args.distant_target_name,
|
||||
args.storage_name
|
||||
);
|
||||
break;
|
||||
|
||||
case COMMAND_LIST:
|
||||
err = cahute_list_storage_entries(
|
||||
link,
|
||||
args.storage_name,
|
||||
&print_storage_entry,
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
|
||||
case COMMAND_RESET:
|
||||
err = cahute_reset_storage(link, args.storage_name);
|
||||
break;
|
||||
|
||||
case COMMAND_OPTIMIZE:
|
||||
err = cahute_optimize_storage(link, args.storage_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = CAHUTE_ERROR_IMPL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err && err != CAHUTE_ERROR_NOOW)
|
||||
goto fail;
|
||||
|
||||
if (progress_displayed)
|
||||
puts("\b\b\b\b\b\bTransfer complete.");
|
||||
|
||||
cahute_close_link(link);
|
||||
|
||||
if (args.local_source_fp && args.local_source_path)
|
||||
fclose(args.local_source_fp);
|
||||
if (args.local_target_fp && args.local_target_path)
|
||||
fclose(args.local_target_fp);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (progress_displayed)
|
||||
puts("\b\b\b\b\b\bError !");
|
||||
|
||||
/* If a link has been initialized, we want to close it. */
|
||||
if (link)
|
||||
cahute_close_link(link);
|
||||
|
||||
/* If files have been opened when parsing args, we want to close them. */
|
||||
if (args.local_source_fp && args.local_source_path)
|
||||
fclose(args.local_source_fp);
|
||||
if (args.local_target_fp && args.local_target_path)
|
||||
fclose(args.local_target_fp);
|
||||
|
||||
/* If a local target path was defined, we want to remove it. */
|
||||
if (args.local_target_path)
|
||||
remove(args.local_target_path);
|
||||
|
||||
/* And now, to display an error corresponding to the obtained error. */
|
||||
switch (err) {
|
||||
case CAHUTE_ERROR_IMPL:
|
||||
fprintf(stderr, error_notimplemented);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_PRIV:
|
||||
fprintf(stderr, error_noaccess);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_NOT_FOUND:
|
||||
fprintf(stderr, error_notfound);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_INCOMPAT:
|
||||
fprintf(stderr, error_unsupported);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_GONE:
|
||||
fprintf(stderr, error_disconnected);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_TOO_MANY:
|
||||
/* The message should have already been displayed in this case. */
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, error_unplanned, av[0]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef P7_H
|
||||
#define P7_H 1
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#define DEFAULT_STORAGE "fls0"
|
||||
|
||||
#define COMMAND_LIST_SERIAL 1
|
||||
#define COMMAND_SEND 2
|
||||
#define COMMAND_GET 3
|
||||
#define COMMAND_COPY 4
|
||||
#define COMMAND_DELETE 5
|
||||
#define COMMAND_LIST 6
|
||||
#define COMMAND_RESET 7
|
||||
#define COMMAND_OPTIMIZE 8
|
||||
#define COMMAND_INFO 9
|
||||
#define COMMAND_IDLE 10
|
||||
|
||||
/**
|
||||
* Parsed argument structure.
|
||||
*
|
||||
* The combinations for the operations on the file system are the following:
|
||||
*
|
||||
* - SEND a {local_source_fp}'s content to a {distant_target_name}, in the
|
||||
* {distant_target_directory_name} directory on {storage_name}.
|
||||
* - GET {distant_source_name}, in the {distant_source_directory_name}
|
||||
* directory on {storage_name}, to {local_target_fp}.
|
||||
* - COPY {distant_source_name}, in the {distant_source_directory_name}
|
||||
* directory, to {distant_target_name}, in the
|
||||
* {distant_target_directory_name}, on {storage_name}.
|
||||
* - DELETE {distant_target_name}, in the {distant_target_directory_name}
|
||||
* directory, on {storage_name}.
|
||||
* - LIST files in the {distant_target_directory_name} directory
|
||||
* on {storage_name}.
|
||||
* - RESET {storage_name}.
|
||||
* - OPTIMIZE {storage_name}.
|
||||
*
|
||||
* General properties:
|
||||
*
|
||||
* @property command Selected subcommand.
|
||||
* @property nice_display Whether nice display is enabled or not.
|
||||
* @property force Whether to force overwrite or not.
|
||||
*
|
||||
* Connection properties:
|
||||
*
|
||||
* @property serial_flags Serial flags to define.
|
||||
* @property serial_speed Speed to use.
|
||||
* @property new_serial_flags Serial flags to update the connection to.
|
||||
* @property new_serial_speed Serial speed to update the connection to.
|
||||
* @property no_init If a connection is established, whether to initialize
|
||||
* the connection (0) or not (1).
|
||||
* @property no_term If a connection is established, whether to terminate
|
||||
* the connection (0) or not (1).
|
||||
* @property change_serial Whether to set new serial attributes or not.
|
||||
* @property serial_name Serial device's name or path.
|
||||
*
|
||||
* Distant filesystem properties:
|
||||
*
|
||||
* @property storage_name Optional storage name for operations with the
|
||||
* calculator.
|
||||
* @property distant_source_directory_name Optional source directory name for
|
||||
* copy, or directory name when getting a file.
|
||||
* @property distant_source_name Source file name for copy, or file name
|
||||
* when getting a file.
|
||||
* @property distant_target_directory_name Optional target directory name for
|
||||
* copy, or directory name when uploading a file.
|
||||
* @property distant_target_name Target file name for copy, or file name
|
||||
* when sending a file.
|
||||
*
|
||||
* Local filesystem properties:
|
||||
*
|
||||
* @property local_source_path Path to the local file when uploading a file.
|
||||
* @property local_source_fp Local FILE object for uploading a file.
|
||||
* @property local_target_path Path to the local file when downloading a file.
|
||||
* @property local_target_fp Local FILE object for downloading a file.
|
||||
*/
|
||||
struct args {
|
||||
int command;
|
||||
int nice_display;
|
||||
int force;
|
||||
|
||||
/* Connection-related parameters. */
|
||||
unsigned long serial_flags;
|
||||
unsigned long serial_speed;
|
||||
unsigned long new_serial_flags;
|
||||
unsigned long new_serial_speed;
|
||||
int no_init;
|
||||
int no_term;
|
||||
int change_serial;
|
||||
char const *serial_name;
|
||||
|
||||
/* Calculator storage related parameters. */
|
||||
char const *storage_name;
|
||||
char const *distant_source_directory_name;
|
||||
char const *distant_source_name;
|
||||
char const *distant_target_directory_name;
|
||||
char const *distant_target_name;
|
||||
|
||||
/* Local data.
|
||||
* The local source fp may be defined without the local source path being
|
||||
* defined, which means we are actually targetting a special stream,
|
||||
* such as stdin. Same for the target with stdout or stderr. */
|
||||
char const *local_source_path;
|
||||
char const *local_target_path;
|
||||
FILE *local_source_fp;
|
||||
FILE *local_target_fp;
|
||||
};
|
||||
|
||||
extern int parse_args(int ac, char **av, struct args *args);
|
||||
|
||||
#endif /* P7_H */
|
|
@ -0,0 +1,745 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "p7.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char const version_message[] =
|
||||
"p7 - from Cahute v" CAHUTE_VERSION
|
||||
" (licensed under CeCILL 2.1)\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
static char const help_main[] =
|
||||
"Usage: %s\n"
|
||||
" [--version|-v] [--help|-h] [-l|--log <level>]\n"
|
||||
" [--com <device>] [--use <params>] [--set <params>] [--reset]\n"
|
||||
" [--no-init] [--no-exit]\n"
|
||||
" <subcommand> [options...]\n"
|
||||
"\n"
|
||||
"Subcommands you can use are:\n"
|
||||
" help Display the help page of the command.\n"
|
||||
" version Display the version message.\n"
|
||||
" list-devices List available serial devices.\n"
|
||||
" info Get information about the calculator.\n"
|
||||
" idle Do nothing once the link is established.\n"
|
||||
" send Send a file to the calculator.\n"
|
||||
" get Get a file from the calculator.\n"
|
||||
" copy Copy a file into another on the calculator.\n"
|
||||
" delete Delete a file on the calculator.\n"
|
||||
" list List files on the distant filesystem.\n"
|
||||
" reset Reset the flash memory.\n"
|
||||
" optimize Optimize the distant filesystem.\n"
|
||||
"\n"
|
||||
"General options:\n"
|
||||
" -h, --help Display the help page of the (sub)command and quit.\n"
|
||||
" -v, --version Display the version message and quit.\n"
|
||||
" -l, --log <level> Logging level to set (default: %s).\n"
|
||||
" One of: info, warning, error, fatal, none.\n"
|
||||
"\n"
|
||||
"Link-related options:\n"
|
||||
" --com <device> Path or name of the serial device with which to\n"
|
||||
" communicate. If this option isn't used, the\n"
|
||||
" program will use USB to find the calculator.\n "
|
||||
" --use <settings> Serial settings to use, when the link is established\n"
|
||||
" over a serial link (i.e. when used with `--com`).\n"
|
||||
" For example, \"9600N2\" represents 9600 bauds, no\n"
|
||||
" parity, and two stop bits.\n"
|
||||
" --set <settings> Serial settings to negotiate with the calculator\n"
|
||||
" (when used with `--com`).\n"
|
||||
" The string has the same format than for `--use`.\n"
|
||||
" --reset Shorthand option for `--set 9600N2`.\n"
|
||||
" --no-init Disable the initiation handshake when the link is\n"
|
||||
" established, for chaining multiple p7 subcommands.\n"
|
||||
" --no-exit Disable the termination handshake when the link is\n"
|
||||
" closed, for chaining multiple p7 subcommands.\n"
|
||||
"\n"
|
||||
"Type \"%s <subcommand> --help\" for some help "
|
||||
"about the subcommand.\n"
|
||||
"\n"
|
||||
"For guides, topics and reference, consult the documentation:\n"
|
||||
" " CAHUTE_URL
|
||||
"\n"
|
||||
"\n"
|
||||
"For reporting issues and vulnerabilities, consult the following guide:\n"
|
||||
" " CAHUTE_ISSUES_URL "\n";
|
||||
|
||||
#define SUBCOMMAND_FOOTER \
|
||||
"\nType \"%s --help\" for other subcommands and general options.\n"
|
||||
|
||||
static char const help_list_devices[] =
|
||||
"Usage: %s list-devices\n"
|
||||
"List serial devices.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_info[] =
|
||||
"Usage: %s info\n"
|
||||
"Get information about the calculator.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_idle[] =
|
||||
"Usage: %s idle\n"
|
||||
"Do nothing while the link is active.\n"
|
||||
"\n"
|
||||
"This subcommand is useful when chaining p7 subcommands, to dedicate a\n"
|
||||
"p7 call to only initiate or terminate the link, or negotiate new\n"
|
||||
"serial settings.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_send[] =
|
||||
"Usage: %s send [options...] <local file>\n"
|
||||
"Send a file to the calculator.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -# Display a nice progress bar.\n"
|
||||
" -f, --force Force overwriting if relevant.\n"
|
||||
" -o, --output <name>\n"
|
||||
" Output filename on the calculator.\n"
|
||||
" By default, the output file name is the base name\n"
|
||||
" of the provided local file path.\n"
|
||||
" -d, --directory <dir>\n"
|
||||
" On-calc directory name in which the file will be\n"
|
||||
" stored. By default, the file is stored at root.\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_get[] =
|
||||
"Usage: %s get [options...] <on-calc filename>\n"
|
||||
"Request a file from the calculator.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -# Display a nice progress bar.\n"
|
||||
" -o, --output <name>\n"
|
||||
" Output local file path, absolute or relative to\n"
|
||||
" the working directory. By default, the file is\n"
|
||||
" stored in the working directory with the name\n"
|
||||
" it had on the calculator.\n"
|
||||
" -d, --directory <dir>\n"
|
||||
" On-calc directory name from which to get the file.\n"
|
||||
" By default, the file is retrieved from root.\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_copy[] =
|
||||
"Usage: %s copy [options...] <source file> <dest file>\n"
|
||||
"Copy a file into the other on the calculator.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -# Display a nice progress bar.\n"
|
||||
" -d, --directory <srcdir>\n"
|
||||
" On-calc directory name in which the source file is\n"
|
||||
" located. By default, root is used.\n"
|
||||
" -t, --to <dstdir> On-calc directory name in which the file should be\n"
|
||||
" copied to. By default, root is used.\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_delete[] =
|
||||
"Usage: %s delete [options...] <on-calc filename>\n"
|
||||
"Delete a file on the calculator.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -d, --directory <dir>\n"
|
||||
" On-calc directory name from which to delete the\n"
|
||||
" file. By default, the file is deleted from root.\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_list[] =
|
||||
"Usage: %s list [options...]\n"
|
||||
"List files on the distant filesystem.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -d, --directory <dir>\n"
|
||||
" On-calc directory name from which to list\n"
|
||||
" files. By default, files are listed from every\n"
|
||||
" directory, including root.\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_reset[] =
|
||||
"Usage: %s reset\n"
|
||||
"Reset the distant filesystem.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
static char const help_optimize[] =
|
||||
"Usage: %s optimize\n"
|
||||
"Optimize the distant filesystem.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" --storage <abc0> Storage device with which to interact (fls0,\n"
|
||||
" crd0). By default, this option is set to "
|
||||
"'" DEFAULT_STORAGE "'.\n" SUBCOMMAND_FOOTER;
|
||||
|
||||
/**
|
||||
* Short options for getopt_long().
|
||||
*/
|
||||
static char const *short_options = "hvfo:d:t:l:#";
|
||||
|
||||
/**
|
||||
* Long options for getopt_long().
|
||||
*/
|
||||
static struct option const long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"com", required_argument, NULL, 'c'},
|
||||
{"storage", required_argument, NULL, 's'},
|
||||
{"force", no_argument, NULL, 'f'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"directory", required_argument, NULL, 'd'},
|
||||
{"to", required_argument, NULL, 't'},
|
||||
{"no-init", no_argument, NULL, 'i'},
|
||||
{"no-start", no_argument, NULL, 'i'},
|
||||
{"no-exit", no_argument, NULL, 'e'},
|
||||
{"no-term", no_argument, NULL, 'e'},
|
||||
{"set", required_argument, NULL, 'S'},
|
||||
{"reset", no_argument, NULL, 'R'},
|
||||
{"use", required_argument, NULL, 'U'},
|
||||
{"log", required_argument, NULL, 'l'},
|
||||
|
||||
/* sentinel */
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse serial attributes.
|
||||
*
|
||||
* The raw string format is "{speed}{parity}{stop bits}", where:
|
||||
*
|
||||
* - Speed is expressed in bauds, e.g. "9600".
|
||||
* - Parity is either "E" for even, "O" for odd and "N" for disabled.
|
||||
* - Stop bits is either "1" or "2".
|
||||
*
|
||||
* An example string is "9600N2" for 9600 bauds, no parity and 2 stop bits.
|
||||
*
|
||||
* @param raw Raw serial attributes.
|
||||
* @param flagsp Pointer to the flags to define.
|
||||
* @param speedp Pointer to the speed to define.
|
||||
* @return Whether an error has occurred (1) or not (0).
|
||||
*/
|
||||
static int parse_serial_attributes(
|
||||
char const *raw,
|
||||
unsigned long *flagsp,
|
||||
unsigned long *speedp
|
||||
) {
|
||||
char const *s;
|
||||
unsigned long speed = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
for (s = raw; *s >= '0' && *s <= '9'; s++)
|
||||
speed = speed * 10 + *s - '0';
|
||||
|
||||
|
||||
if (s == raw)
|
||||
return 1;
|
||||
|
||||
switch (speed) {
|
||||
case 300:
|
||||
case 600:
|
||||
case 1200:
|
||||
case 2400:
|
||||
case 4800:
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 115200:
|
||||
case 230400:
|
||||
case 460800:
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*s == 'N')
|
||||
flags |= CAHUTE_SERIAL_PARITY_OFF;
|
||||
else if (*s == 'E')
|
||||
flags |= CAHUTE_SERIAL_PARITY_EVEN;
|
||||
else if (*s == 'O')
|
||||
flags |= CAHUTE_SERIAL_PARITY_ODD;
|
||||
else
|
||||
return 1;
|
||||
|
||||
s++;
|
||||
if (*s == '1')
|
||||
flags |= CAHUTE_SERIAL_STOP_ONE;
|
||||
else if (*s == '2')
|
||||
flags |= CAHUTE_SERIAL_STOP_TWO;
|
||||
else
|
||||
return 1;
|
||||
|
||||
s++;
|
||||
if (*s) /* String should be terminated. */
|
||||
return 1;
|
||||
|
||||
*speedp = speed;
|
||||
*flagsp = flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an on-calc directory name.
|
||||
*
|
||||
* @param name Directory name to check.
|
||||
* @return 1 if all checks pass, 0 otherwise.
|
||||
*/
|
||||
static inline int check_directory_name(char const *name) {
|
||||
size_t n;
|
||||
|
||||
if (!name)
|
||||
return 1;
|
||||
|
||||
n = strnlen(name, 9);
|
||||
if (n > 9)
|
||||
return 0;
|
||||
|
||||
for (; n--; name++)
|
||||
if (!isascii(*name) || *name == '/' || *name == '\\'
|
||||
|| (!isgraph(*name) && !isblank(*name)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an on-calc file name.
|
||||
*
|
||||
* @param name Directory name to check.
|
||||
* @return 1 if all checks pass, 0 otherwise.
|
||||
*/
|
||||
static inline int check_file_name(char const *name) {
|
||||
size_t n;
|
||||
|
||||
if (!name)
|
||||
return 1;
|
||||
|
||||
n = strnlen(name, 13);
|
||||
if (n > 12)
|
||||
return 0;
|
||||
|
||||
for (; n--; name++)
|
||||
if (!isascii(*name) || *name == '/' || *name == '\\'
|
||||
|| (!isgraph(*name) && !isblank(*name)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line parameters, and handle help and version messages.
|
||||
*
|
||||
* Note that since we use getopt_long(), the argv array is actually reorganized
|
||||
* to move positional parameters at the end of the array, hence why argv
|
||||
* is of "char **" type, and not "char const * const *".
|
||||
*
|
||||
* @param argc Argument count, as provided to main().
|
||||
* @param argv Argument values, as provided to main().
|
||||
* @param args Parsed argument structure to feed for use by caller.
|
||||
* @return Whether parameters were successfully parsed (1), or not (0).
|
||||
*/
|
||||
int parse_args(int argc, char **argv, struct args *args) {
|
||||
char const *command = argv[0], *subcommand;
|
||||
char **params;
|
||||
char const *o_directory = NULL;
|
||||
char const *o_target_directory = NULL;
|
||||
char const *o_output = NULL;
|
||||
char const *o_storage = DEFAULT_STORAGE;
|
||||
int option, help = 0, param_count;
|
||||
|
||||
/* Default parsed arguments.
|
||||
* By default, the serial speed is defined as 9600N2. */
|
||||
args->command = COMMAND_IDLE;
|
||||
args->nice_display = 1;
|
||||
|
||||
args->serial_flags = CAHUTE_SERIAL_PARITY_OFF | CAHUTE_SERIAL_STOP_TWO;
|
||||
args->serial_speed = 9600;
|
||||
args->new_serial_flags = CAHUTE_SERIAL_PARITY_OFF | CAHUTE_SERIAL_STOP_TWO;
|
||||
args->new_serial_speed = 9600;
|
||||
args->no_init = 0;
|
||||
args->no_term = 0;
|
||||
args->change_serial = 0;
|
||||
args->serial_name = NULL;
|
||||
|
||||
args->storage_name = NULL;
|
||||
args->distant_source_directory_name = NULL;
|
||||
args->distant_source_name = NULL;
|
||||
args->distant_target_directory_name = NULL;
|
||||
args->distant_target_name = NULL;
|
||||
args->force = 0;
|
||||
|
||||
args->local_source_path = NULL;
|
||||
args->local_target_path = NULL;
|
||||
args->local_source_fp = NULL;
|
||||
args->local_target_fp = NULL;
|
||||
|
||||
opterr = 0;
|
||||
|
||||
while (1) {
|
||||
option = getopt_long(argc, argv, short_options, long_options, NULL);
|
||||
if (option < 0)
|
||||
break;
|
||||
|
||||
switch (option) {
|
||||
case 'h':
|
||||
/* -h, --help: display the help message and quit.
|
||||
* This is not done immediately because the displayed help
|
||||
* message depends on the parameters. */
|
||||
help = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
/* -v, --version: display the version message and quit. */
|
||||
puts(version_message);
|
||||
return 0;
|
||||
|
||||
case 'f':
|
||||
/* -f, --force: overwrite without asking. */
|
||||
args->force = 1;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
/* -#: enable the loading bar. */
|
||||
args->nice_display = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* -l, --log: set the logging level. */
|
||||
set_log_level(optarg);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
/* -o, --output: set the output filename.
|
||||
*
|
||||
* This can have multiple meanings depending on the subcommand:
|
||||
*
|
||||
* - With 'send' as 'distant_target_name'.
|
||||
* - With 'get', as 'distant_source_name. */
|
||||
o_output = optarg;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
/* -d, --directory: set the output directory on the calculator.
|
||||
*
|
||||
* This can have multiple meanings depending on the subcommand:
|
||||
*
|
||||
* - With 'send', as 'distant_target_directory_name'.
|
||||
* - With 'get' and 'copy', as 'distant_source_directory_name'. */
|
||||
o_directory = optarg;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
/* -t, --to: set the destination directory for copy.
|
||||
*
|
||||
* This is only the 'distant_target_directory_name' for 'copy'. */
|
||||
o_target_directory = optarg;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
/* --com: set the serial port. */
|
||||
args->serial_name = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
/* --storage: set the storage. */
|
||||
o_storage = optarg;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
/* --no-init: disable link initialization. */
|
||||
args->no_init = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
/* --no-exit: disable link termination. */
|
||||
args->no_term = 1;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
/* --use: use initial serial settings. */
|
||||
if (parse_serial_attributes(
|
||||
optarg,
|
||||
&args->serial_flags,
|
||||
&args->serial_speed
|
||||
)) {
|
||||
fprintf(stderr, "-u, --use: invalid format!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
/* --set: set serial settings to negotiate with the calculator. */
|
||||
if (parse_serial_attributes(
|
||||
optarg,
|
||||
&args->new_serial_flags,
|
||||
&args->new_serial_speed
|
||||
)) {
|
||||
fprintf(stderr, "-s, --set: invalid format!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->change_serial = 1;
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
/* --reset: reset serial settings. */
|
||||
args->new_serial_flags =
|
||||
CAHUTE_SERIAL_PARITY_OFF | CAHUTE_SERIAL_STOP_TWO;
|
||||
args->new_serial_speed = 9600;
|
||||
args->change_serial = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* Erroneous option usage. */
|
||||
if (optopt == 'o')
|
||||
fprintf(stderr, "-o, --output: expected an argument\n");
|
||||
else if (optopt == 'd')
|
||||
fprintf(stderr, "-d, --directory: expected an argument\n");
|
||||
else if (optopt == 't')
|
||||
fprintf(stderr, "-t, --to: expected an argument\n");
|
||||
else if (optopt == 'c')
|
||||
fprintf(stderr, "--com: expected an argument\n");
|
||||
else if (optopt == 's')
|
||||
fprintf(stderr, "--storage: expected an argument\n");
|
||||
else
|
||||
/* We ignore unknown options. */
|
||||
break;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
param_count = argc - optind;
|
||||
params = &argv[optind];
|
||||
|
||||
if (!param_count || !strcmp(params[0], "help")) {
|
||||
printf(help_main, command, get_current_log_level(), command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subcommand = params[0];
|
||||
params++;
|
||||
param_count--;
|
||||
|
||||
if (!strcmp(subcommand, "version")) {
|
||||
puts(version_message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(subcommand, "list-devices")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_list_devices, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_LIST_SERIAL;
|
||||
} else if (!strcmp(subcommand, "send")) {
|
||||
if (help || param_count != 1) {
|
||||
printf(help_send, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!o_output) {
|
||||
/* By default, we want to determine the output name from the
|
||||
* local path. */
|
||||
o_output = strrchr(params[0], '/');
|
||||
if (!o_output)
|
||||
o_output = params[0];
|
||||
}
|
||||
|
||||
args->command = COMMAND_SEND;
|
||||
args->storage_name = o_storage;
|
||||
args->local_source_path = params[0];
|
||||
args->distant_target_directory_name = o_directory;
|
||||
args->distant_target_name = o_output;
|
||||
} else if (!strcmp(subcommand, "get")) {
|
||||
if (help || param_count != 1) {
|
||||
printf(help_get, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (o_output == NULL)
|
||||
/* By default, we want the local name to be the same as the
|
||||
* distant file name. */
|
||||
o_output = params[0];
|
||||
|
||||
args->command = COMMAND_GET;
|
||||
args->storage_name = o_storage;
|
||||
args->distant_source_directory_name = o_directory;
|
||||
args->distant_source_name = params[0];
|
||||
|
||||
if (!strcmp(o_output, "-")) /* Standard output. */
|
||||
args->local_target_fp = stdout;
|
||||
else
|
||||
args->local_target_path = o_output;
|
||||
} else if (!strcmp(subcommand, "copy") || !strcmp(subcommand, "cp")) {
|
||||
if (help || param_count != 2) {
|
||||
printf(help_copy, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_COPY;
|
||||
args->storage_name = o_storage;
|
||||
args->distant_source_directory_name = o_directory;
|
||||
args->distant_source_name = params[0];
|
||||
args->distant_target_directory_name = o_target_directory;
|
||||
args->distant_target_name = params[1];
|
||||
} else if (!strcmp(subcommand, "delete") || !strcmp(subcommand, "del")) {
|
||||
if (help || param_count != 1) {
|
||||
printf(help_delete, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_DELETE;
|
||||
args->storage_name = o_storage;
|
||||
args->distant_target_directory_name = o_directory;
|
||||
args->distant_target_name = params[0];
|
||||
} else if (!strcmp(subcommand, "list") || !strcmp(subcommand, "ls")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_list, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_LIST;
|
||||
args->storage_name = o_storage;
|
||||
args->distant_target_directory_name = o_directory;
|
||||
} else if (!strcmp(subcommand, "reset")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_reset, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_RESET;
|
||||
args->storage_name = o_storage;
|
||||
} else if (!strcmp(subcommand, "optimize")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_optimize, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_OPTIMIZE;
|
||||
args->storage_name = o_storage;
|
||||
} else if (!strcmp(subcommand, "info")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_info, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_INFO;
|
||||
} else if (!strcmp(subcommand, "idle") || !strcmp(subcommand, "laze")) {
|
||||
if (help || param_count != 0) {
|
||||
printf(help_idle, command, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->command = COMMAND_IDLE;
|
||||
} else {
|
||||
/* The subcommand is unknown. */
|
||||
printf(help_main, command, get_current_log_level(), command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args->storage_name
|
||||
&& (strlen(args->storage_name) != 4 || !isascii(args->storage_name[0])
|
||||
|| !islower(args->storage_name[0])
|
||||
|| !isascii(args->storage_name[1])
|
||||
|| !islower(args->storage_name[1])
|
||||
|| !isascii(args->storage_name[2])
|
||||
|| !isascii(args->storage_name[2])
|
||||
|| !isascii(args->storage_name[3])
|
||||
|| !isdigit(args->storage_name[3]))) {
|
||||
fprintf(stderr, "Invalid storage name format.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!check_directory_name(args->distant_source_directory_name)) {
|
||||
fprintf(stderr, "Invalid source directory name format.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!check_file_name(args->distant_source_name)) {
|
||||
fprintf(stderr, "Invalid source file name format.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!check_directory_name(args->distant_target_directory_name)) {
|
||||
fprintf(stderr, "Invalid target directory name format.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!check_file_name(args->distant_target_name)) {
|
||||
fprintf(stderr, "Invalid target file name format.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open the local source path if a path is given. */
|
||||
if (args->local_source_path && !args->local_source_fp) {
|
||||
args->local_source_fp = fopen(args->local_source_path, "r");
|
||||
if (!args->local_source_fp) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Can't open '%s': %s\n",
|
||||
args->local_source_path,
|
||||
strerror(errno)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the local target path if a path is given. */
|
||||
if (args->local_target_path && !args->local_target_fp) {
|
||||
args->local_target_fp = fopen(args->local_target_path, "w+");
|
||||
if (!args->local_target_fp) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Can't open '%s': %s\n",
|
||||
args->local_target_path,
|
||||
strerror(errno)
|
||||
);
|
||||
if (args->local_source_path && args->local_source_fp)
|
||||
fclose(args->local_source_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,494 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "p7screen.h"
|
||||
#include <string.h>
|
||||
#include <SDL.h>
|
||||
|
||||
static Uint32 const dual_pixels[] = {0xFFFFFF, 0xAAAAAA, 0x777777, 0x000000};
|
||||
|
||||
/**
|
||||
* Display cookie.
|
||||
*
|
||||
* @property window Window that contains the surface.
|
||||
* @property renderer Renderer for the window.
|
||||
* @property texture Texture that covers the window.
|
||||
* @property saved_width Saved width from when the window was first opened.
|
||||
* @property saved_height Saved height from when the window was first opened.
|
||||
* @property zoom Zoom with which to draw the window.
|
||||
*/
|
||||
struct display_cookie {
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
int saved_width;
|
||||
int saved_height;
|
||||
int zoom;
|
||||
};
|
||||
|
||||
static char const error_notfound[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in PROJ mode?\n"
|
||||
"- Have you tried unplugging, plugging and selecting Projector on "
|
||||
"pop-up?\n"
|
||||
"- Have you tried changing the cable?\n";
|
||||
|
||||
static char const error_noaccess[] =
|
||||
"Could not get access to the calculator.\n"
|
||||
"Install the appropriate udev rule, or run as root.\n";
|
||||
|
||||
static char const error_unplanned[] =
|
||||
"The calculator didn't act as planned.\n"
|
||||
"Stop receive mode on calculator and start it again before re-running "
|
||||
"p7screen.\n";
|
||||
|
||||
/**
|
||||
* Update the texture pixels with the frame contents.
|
||||
*
|
||||
* Both the destination format and all source formats are organized into
|
||||
* lines first, columns seconds, which means a picture with pixels ABCDEF
|
||||
* represent the following:
|
||||
*
|
||||
* A B C
|
||||
* D E F
|
||||
*
|
||||
* However, the destination format also includes a zoom, which means that
|
||||
* the above picture will need to be represented the following for a zoom
|
||||
* of 3:
|
||||
*
|
||||
* * [A] A A B B B C C C
|
||||
* / A A A B B B C C C
|
||||
* / A A A B B B C C C
|
||||
* * [D] D D E E E F F F
|
||||
* / D D D E E E F F F
|
||||
* / D D D E E E F F F
|
||||
*
|
||||
* For every line we read from the source format, we compute the origin
|
||||
* of the destination line into ``oy``, which will be:
|
||||
*
|
||||
* - The index of the line, starting at 0...
|
||||
* - ... multiplied by the zoom (number of destination lines per source
|
||||
* line)...
|
||||
* - ... multiplied by the width (number of pixels in one line)...
|
||||
* - ... multiplied by the zoom again (number of destination pixels per
|
||||
* source pixel).
|
||||
*
|
||||
* Once we have this, the idea is that we only compute the first destination
|
||||
* line per source line, and copy it for the rest of the destination lines
|
||||
* corresponding to the same source line. In the example, lines prefixed
|
||||
* with "*" are computed directly, and lines prefixed with "/" are copied
|
||||
* from lines prefixed with "*".
|
||||
*
|
||||
* Then, for every pixel in the source frame, we copy it zoom times into
|
||||
* the destination frame.
|
||||
*
|
||||
* The basic template for every case is the following:
|
||||
*
|
||||
* for (int y = 0, oy = 0; y < height; y++, oy += zoom_line_size) {
|
||||
* for (int x = 0, ox = 0; x < width; x++, ox += zoom) {
|
||||
* Uint32 pixel = ...; // format-specific stuff
|
||||
*
|
||||
* for (int dx = zoom - 1; dx >= 0; dx--)
|
||||
* pixels[oy + ox + dx] = pixel;
|
||||
* }
|
||||
*
|
||||
* for (int py = oy + zoom_line_size - line_size; py > oy;
|
||||
* py -= line_size)
|
||||
* memcpy(&pixels[py], &pixels[oy], line_size << 2);
|
||||
* }
|
||||
*
|
||||
* Note that we use 'line_size << 2' at the end, and not 'line_size',
|
||||
* because we are dealing with 32-bit integers and not 8-bit integers here,
|
||||
* so we need to multiply by 4 the memory size to copy.
|
||||
*
|
||||
* Also note that we prefer the "one loop by format" instead of "one loop
|
||||
* for every format", because not having additional conditions in the main
|
||||
* body of the loop makes it faster.
|
||||
*
|
||||
* Also note that since we're on picture format conversions, with potentially
|
||||
* a lot of pixels, we want to use arithmetic or bitwise operations as much
|
||||
* as possible, since conditional operations disrupt the pipeline.
|
||||
*
|
||||
* @param pixels Pixels array to update, using sRGB colors on 32-bits.
|
||||
* @param frame Frame to update the pixels with.
|
||||
* @param zoom Zoom to draw the frame with.
|
||||
*/
|
||||
static void
|
||||
update_texture_pixels(Uint32 *pixels, cahute_frame const *frame, int zoom) {
|
||||
int width = frame->cahute_frame_width;
|
||||
int height = frame->cahute_frame_height;
|
||||
int line_size = zoom * width;
|
||||
int zoom_line_size = line_size * zoom;
|
||||
int y, oy, x, ox, dx, py, mask;
|
||||
cahute_u8 const *data = frame->cahute_frame_data;
|
||||
cahute_u8 const *data2;
|
||||
|
||||
switch (frame->cahute_frame_format) {
|
||||
case CAHUTE_PICTURE_FORMAT_1BIT_MONO:
|
||||
for (y = 0, oy = 0; y < height; y++, oy += zoom_line_size) {
|
||||
/* The mask will be right-shifted every pixel, unless it's 1,
|
||||
* which leads to the mask being reset to 128 using
|
||||
* '(mask & 1) << 7'. */
|
||||
mask = 128;
|
||||
|
||||
for (x = 0, ox = 0; x < width; x++, ox += zoom) {
|
||||
Uint32 pixel = *data & mask ? 0x000000 : 0xFFFFFF;
|
||||
|
||||
for (dx = zoom - 1; dx >= 0; dx--)
|
||||
pixels[oy + ox + dx] = pixel;
|
||||
|
||||
/* Go to the next byte if we're resetting the mask from
|
||||
* 1 back to 128. */
|
||||
data += mask & 1;
|
||||
mask = (mask >> 1) | ((mask & 1) << 7);
|
||||
}
|
||||
|
||||
for (py = oy + zoom_line_size - line_size; py > oy;
|
||||
py -= line_size)
|
||||
memcpy(&pixels[py], &pixels[oy], line_size << 2);
|
||||
|
||||
/* The start of the next line is aligned, if we are not aligned
|
||||
* already, we need to align ourselves. */
|
||||
data += (~mask & 128) >> 7;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAHUTE_PICTURE_FORMAT_1BIT_DUAL:
|
||||
data2 = data + height * ((width >> 8) + !!(width & 7));
|
||||
|
||||
for (y = 0, oy = 0; y < height; y++, oy += zoom_line_size) {
|
||||
/* Same logic as for 1-bit monochrome encoding. */
|
||||
mask = 128;
|
||||
|
||||
for (x = 0, ox = 0; x < width; x++, ox += zoom) {
|
||||
/* We obtain the first bit and the second bit, then we need
|
||||
* to place the first bit in the before-last rank (i.e. 0bX0)
|
||||
* and the second bit to the last rank (i.e. 0bX).
|
||||
*
|
||||
* In order to do this, we determine the position of the
|
||||
* bit in the original byte using '7 - (x & 7)'. Here's
|
||||
* the table showing that it works:
|
||||
*
|
||||
* +-------+-------------+------+
|
||||
* | x & 7 | 7 - (x & 7) | Rank |
|
||||
* +-------+-------------+------+
|
||||
* | 0 | 7 | 7 |
|
||||
* | 1 | 6 | 6 |
|
||||
* | 2 | 5 | 5 |
|
||||
* | 3 | 4 | 4 |
|
||||
* | 4 | 3 | 3 |
|
||||
* | 5 | 2 | 2 |
|
||||
* | 6 | 1 | 1 |
|
||||
* | 7 | 0 | 0 |
|
||||
* +-------+-------------+-----+
|
||||
*
|
||||
* Since both the first and second bit have the same rank,
|
||||
* we can just shift the first bit a rank to the left, then
|
||||
* shift the whole number down to rank 0 to obtain the 2-bit
|
||||
* result.
|
||||
*
|
||||
* NOTE: Before shifting the first bit left, we need to
|
||||
* ensure that the operation is run on an integer more
|
||||
* than 8-bit long, otherwise the bit will be lost. */
|
||||
int index = *data & mask;
|
||||
index = (index << 1) | (*data2 & mask);
|
||||
index >>= 7 - (x & 7);
|
||||
Uint32 pixel = dual_pixels[index & 3];
|
||||
|
||||
for (dx = zoom - 1; dx >= 0; dx--)
|
||||
pixels[oy + ox + dx] = pixel;
|
||||
|
||||
data += mask & 1;
|
||||
data2 += mask & 1;
|
||||
mask = (mask >> 1) | ((mask & 1) << 7);
|
||||
}
|
||||
|
||||
for (py = oy + zoom_line_size - line_size; py > oy;
|
||||
py -= line_size)
|
||||
memcpy(&pixels[py], &pixels[oy], line_size << 2);
|
||||
|
||||
data += (~mask & 128) >> 7;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAHUTE_PICTURE_FORMAT_4BIT_RGB_PACKED:
|
||||
mask = 240; /* 0b11110000 */
|
||||
|
||||
for (y = 0, oy = 0; y < height; y++, oy += zoom_line_size) {
|
||||
for (x = 0, ox = 0; x < width; x++, ox += zoom) {
|
||||
int raw_value = *data & mask;
|
||||
Uint32 pixel = 0x000000;
|
||||
|
||||
/* R bit in high and low nibble is 136 = 0b1000 1000.
|
||||
* G bit in high and low nibble is 68 = 0b0100 0100.
|
||||
* B bit in high and low nibble is 34 = 0b0010 0010. */
|
||||
if (raw_value & 136)
|
||||
pixel |= 0xFF0000;
|
||||
if (raw_value & 68)
|
||||
pixel |= 0x00FF00;
|
||||
if (raw_value & 34)
|
||||
pixel |= 0x0000FF;
|
||||
|
||||
for (dx = zoom - 1; dx >= 0; dx--)
|
||||
pixels[oy + ox + dx] = pixel;
|
||||
|
||||
data += mask & 1;
|
||||
mask = ~mask & 255;
|
||||
}
|
||||
|
||||
for (py = oy + zoom_line_size - line_size; py > oy;
|
||||
py -= line_size)
|
||||
memcpy(&pixels[py], &pixels[oy], line_size << 2);
|
||||
|
||||
/* No end-of-line conditional re-alignment here, we are on a
|
||||
* packed format. */
|
||||
}
|
||||
break;
|
||||
|
||||
case CAHUTE_PICTURE_FORMAT_16BIT_R5G6B5:
|
||||
for (y = 0, oy = 0; y < height; y++, oy += zoom_line_size) {
|
||||
for (x = 0, ox = 0; x < width; x++, ox += zoom) {
|
||||
/* We have a 16-bit integer being 0bRRRRRGGGGGGBBBBB.
|
||||
* We need to extract these using masks, and place it
|
||||
* at the right ranks in the resulting 24-bit RGB pixel. */
|
||||
unsigned long raw = (data[0] << 8) | data[1];
|
||||
Uint32 pixel = ((raw >> 11) & 31) << 19
|
||||
| ((raw >> 5) & 63) << 10 | (raw & 31) << 3;
|
||||
|
||||
for (dx = zoom - 1; dx >= 0; dx--)
|
||||
pixels[oy + ox + dx] = pixel;
|
||||
|
||||
data += 2;
|
||||
}
|
||||
|
||||
for (py = oy + zoom_line_size - line_size; py > oy;
|
||||
py -= line_size)
|
||||
memcpy(&pixels[py], &pixels[oy], line_size << 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(
|
||||
stderr,
|
||||
"!! Unhandled picture format %d\n",
|
||||
frame->cahute_frame_format
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to display the screen frame.
|
||||
*
|
||||
* @param cookie Display cookie.
|
||||
* @param frame Frame to display.
|
||||
* @return Whether we want to interrupt the flow.
|
||||
*/
|
||||
static int
|
||||
display_frame(struct display_cookie *cookie, cahute_frame const *frame) {
|
||||
int width, height, format, zoom;
|
||||
|
||||
width = frame->cahute_frame_width;
|
||||
height = frame->cahute_frame_height;
|
||||
format = frame->cahute_frame_format;
|
||||
zoom = cookie->zoom;
|
||||
|
||||
if (format != CAHUTE_PICTURE_FORMAT_1BIT_MONO
|
||||
&& format != CAHUTE_PICTURE_FORMAT_1BIT_DUAL
|
||||
&& format != CAHUTE_PICTURE_FORMAT_4BIT_RGB_PACKED
|
||||
&& format != CAHUTE_PICTURE_FORMAT_16BIT_R5G6B5) {
|
||||
fprintf(stderr, "Unsupported format %d.\n", format);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!cookie->window) {
|
||||
/* We haven't got a window, our objective is to create one,
|
||||
* with a renderer and a texture. First, let's create the
|
||||
* window. */
|
||||
cookie->window = SDL_CreateWindow(
|
||||
"p7screen",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width * zoom,
|
||||
height * zoom,
|
||||
0
|
||||
);
|
||||
if (!cookie->window) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Couldn't create the window: %s\n",
|
||||
SDL_GetError()
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Then let's create the renderer. */
|
||||
cookie->renderer =
|
||||
SDL_CreateRenderer(cookie->window, -1, SDL_RENDERER_SOFTWARE);
|
||||
if (!cookie->renderer) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Couldn't create the renderer: %s\n",
|
||||
SDL_GetError()
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Finally, create the texture we're gonna use for drawing
|
||||
* the picture as a classic ARGB pixel matric (8 bits per
|
||||
* component). */
|
||||
cookie->texture = SDL_CreateTexture(
|
||||
cookie->renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
width * zoom,
|
||||
height * zoom
|
||||
);
|
||||
if (!cookie->texture) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Couldn't create the texture: %s\n",
|
||||
SDL_GetError()
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cookie->saved_width = width;
|
||||
cookie->saved_height = height;
|
||||
|
||||
puts("Turn off your calculator (SHIFT+AC) when you have finished.\n");
|
||||
} else if (cookie->saved_width != width || cookie->saved_height != height) {
|
||||
/* The dimensions have changed somehow, we don't support this. */
|
||||
fprintf(stderr, "Unmanaged dimensions changed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the data. */
|
||||
{
|
||||
Uint32 *texture_pixels;
|
||||
int pitch;
|
||||
|
||||
SDL_LockTexture(
|
||||
cookie->texture,
|
||||
NULL,
|
||||
(void **)&texture_pixels,
|
||||
&pitch
|
||||
);
|
||||
|
||||
update_texture_pixels(texture_pixels, frame, cookie->zoom);
|
||||
|
||||
SDL_UnlockTexture(cookie->texture);
|
||||
}
|
||||
|
||||
SDL_RenderCopy(cookie->renderer, cookie->texture, NULL, NULL);
|
||||
SDL_RenderPresent(cookie->renderer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point of the program.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
* @return Exit status code.
|
||||
*/
|
||||
int main(int ac, char **av) {
|
||||
cahute_link *link = NULL;
|
||||
struct args args;
|
||||
struct display_cookie cookie;
|
||||
int bus, address, err, ret = 0;
|
||||
|
||||
if (!parse_args(ac, av, &args))
|
||||
return 0;
|
||||
|
||||
if ((err = find_usb_calculator(1, &bus, &address))
|
||||
|| (err = cahute_open_usb_link(&link, CAHUTE_USB_OHP, bus, address))) {
|
||||
switch (err) {
|
||||
case CAHUTE_ERROR_NOT_FOUND:
|
||||
fprintf(stderr, error_notfound);
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_PRIV:
|
||||
fprintf(stderr, error_noaccess);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, error_unplanned);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the SDL. */
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
fprintf(stderr, "Failed to initialize SDL: %s\n", SDL_GetError());
|
||||
cahute_close_link(link);
|
||||
return 3;
|
||||
}
|
||||
atexit(SDL_Quit);
|
||||
|
||||
cookie.window = NULL;
|
||||
cookie.renderer = NULL;
|
||||
cookie.texture = NULL;
|
||||
cookie.saved_width = -1;
|
||||
cookie.saved_height = -1;
|
||||
cookie.zoom = args.zoom;
|
||||
|
||||
err = cahute_receive_screen(
|
||||
link,
|
||||
(cahute_process_frame_func *)display_frame,
|
||||
&cookie
|
||||
);
|
||||
if (err) {
|
||||
ret = 1;
|
||||
switch (err) {
|
||||
case CAHUTE_ERROR_INT:
|
||||
/* Interrupted; the error message was already displayed. */
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_GONE:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, error_unplanned);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie.texture)
|
||||
SDL_DestroyTexture(cookie.texture);
|
||||
if (cookie.renderer)
|
||||
SDL_DestroyRenderer(cookie.renderer);
|
||||
if (cookie.window)
|
||||
SDL_DestroyWindow(cookie.window);
|
||||
|
||||
cahute_close_link(link);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef P7SCREEN_H
|
||||
#define P7SCREEN_H 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#define DEFAULT_ZOOM 2
|
||||
|
||||
/**
|
||||
* Parsed argument structure.
|
||||
*
|
||||
* @property zoom Zoom from 1 to 16 (i.e. a distant pixel is 1x1 to 16x16).
|
||||
*/
|
||||
struct args {
|
||||
int zoom;
|
||||
};
|
||||
|
||||
extern int parse_args(int ac, char **av, struct args *args);
|
||||
|
||||
#endif /* P7SCREEN_H */
|
|
@ -0,0 +1,155 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2016-2017, 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "p7screen.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static char const version_message[] =
|
||||
"p7screen - from Cahute v" CAHUTE_VERSION
|
||||
" (licensed under CeCILL 2.1)\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
static char const help_message[] =
|
||||
"Usage: %s\n"
|
||||
" [--help|-h] [--version|-v]\n"
|
||||
"\n"
|
||||
"Displays the streamed screen from a CASIO calculator connected by USB.\n"
|
||||
"\n"
|
||||
"Options are:\n"
|
||||
" -h, --help Display this help page\n"
|
||||
" -v, --version Displays the version\n"
|
||||
" -l, --log <level> Logging level to set (default: %s).\n"
|
||||
" One of: info, warning, error, fatal, none.\n"
|
||||
" -z, --zoom <zoom> Change the zoom (1 to 16)\n"
|
||||
" By default, the zoom will be %d.\n"
|
||||
"\n"
|
||||
"For guides, topics and reference, consult the documentation:\n"
|
||||
" " CAHUTE_URL
|
||||
"\n"
|
||||
"\n"
|
||||
"For reporting issues and vulnerabilities, consult the following guide:\n"
|
||||
" " CAHUTE_ISSUES_URL "\n";
|
||||
|
||||
/**
|
||||
* Short options for getopt_long().
|
||||
*/
|
||||
char const *short_options = "hvz:l:";
|
||||
|
||||
/**
|
||||
* Long options for getopt_long().
|
||||
*/
|
||||
struct option const long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"zoom", required_argument, NULL, 'z'},
|
||||
{"log", required_argument, NULL, 'l'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse command-line parameters, and handle help and version messages.
|
||||
*
|
||||
* Note that since we use getopt_long(), the argv array is actually
|
||||
* reorganized to move positional parameters at the end of the array, hence
|
||||
* why argv is of "char **" type, and not "char const * const *".
|
||||
*
|
||||
* @param argc Argument count, as provided to main().
|
||||
* @param argv Argument values, as provided to main().
|
||||
* @param args Parsed argument structure to feed for use by the caller.
|
||||
* @return Whether parameters were successfully parsed (1), or not (0).
|
||||
*/
|
||||
int parse_args(int argc, char **argv, struct args *args) {
|
||||
int help = 0, zoom, option;
|
||||
|
||||
/* Default parsed arguments. */
|
||||
args->zoom = DEFAULT_ZOOM;
|
||||
|
||||
opterr = 0;
|
||||
|
||||
while (1) {
|
||||
option = getopt_long(argc, argv, short_options, long_options, NULL);
|
||||
if (option < 0)
|
||||
break;
|
||||
|
||||
switch (option) {
|
||||
case 'h':
|
||||
/* -h, --help: display the help message and quit. */
|
||||
help = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
/* -v, --version: display the version message and quit. */
|
||||
puts(version_message);
|
||||
return 0;
|
||||
|
||||
case 'z':
|
||||
/* --zoom: set the zoom as an integer between 1 and 16. */
|
||||
zoom = atoi(optarg);
|
||||
if (zoom < 1 || zoom > 16) {
|
||||
fprintf(stderr, "-z, --zoom: should be between 1 and 16\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
args->zoom = zoom;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
/* -l, --log: set the logging level. */
|
||||
set_log_level(optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* Erroneous option usage. */
|
||||
if (optopt == 'z')
|
||||
fprintf(stderr, "-z, --zoom: expected an argument\n");
|
||||
else
|
||||
/* We ignore unknown options. */
|
||||
break;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* p7screen is used without parameters.
|
||||
* If there is any, we want to print the help and quit. */
|
||||
if (argc - optind)
|
||||
help = 1;
|
||||
|
||||
/* If we want to display the help message, do it here! */
|
||||
if (help) {
|
||||
printf(help_message, argv[0], get_current_log_level(), DEFAULT_ZOOM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "xfer9860.h"
|
||||
#include "common.h"
|
||||
|
||||
static char const error_notfound[] =
|
||||
"Could not connect to the calculator.\n"
|
||||
"- Is it plugged in and in receive mode?\n"
|
||||
"- Have you tried changing the cable?\n";
|
||||
|
||||
/**
|
||||
* Display device information.
|
||||
*
|
||||
* @param link Link to use to obtain the information.
|
||||
* @return Cahute error.
|
||||
*/
|
||||
static int print_device_info(cahute_link *link) {
|
||||
unsigned long capacity;
|
||||
int err;
|
||||
|
||||
if ((err = cahute_request_storage_capacity(link, "fls0", &capacity)))
|
||||
return err;
|
||||
|
||||
/* 1572864 is a special value taken from xfer9860.
|
||||
* It may not be accurate for the device. */
|
||||
printf(
|
||||
"Storage memory: %lu%% (%luo) available.\n",
|
||||
100 * capacity / 1572864,
|
||||
capacity
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point to the program.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
* @return Exit code for the program.
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
struct args args;
|
||||
cahute_link *link = NULL;
|
||||
int bus, address, err = 0;
|
||||
|
||||
/* Since xfer9860 has no logging level of any kind, we disable logging
|
||||
* entirely here. */
|
||||
cahute_set_log_level(CAHUTE_LOGLEVEL_NONE);
|
||||
|
||||
if (!parse_args(argc, argv, &args))
|
||||
return 0;
|
||||
if ((err = find_usb_calculator(0, &bus, &address)))
|
||||
goto fail;
|
||||
if ((err = cahute_open_usb_link(&link, 0, bus, address)))
|
||||
goto fail;
|
||||
|
||||
switch (args.operation) {
|
||||
case OPERATION_UPLOAD:
|
||||
err = cahute_send_file_to_storage(
|
||||
link,
|
||||
CAHUTE_SEND_FILE_FLAG_FORCE | CAHUTE_SEND_FILE_FLAG_OPTIMIZE,
|
||||
NULL,
|
||||
args.distant_target_name,
|
||||
"fls0",
|
||||
args.local_source_fp,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
|
||||
case OPERATION_DOWNLOAD:
|
||||
err = cahute_request_file_from_storage(
|
||||
link,
|
||||
NULL,
|
||||
args.distant_source_name,
|
||||
"fls0",
|
||||
args.local_target_fp,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
|
||||
case OPERATION_OPTIMIZE:
|
||||
err = cahute_optimize_storage(link, "fls0");
|
||||
break;
|
||||
|
||||
case OPERATION_INFO:
|
||||
err = print_device_info(link);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = CAHUTE_ERROR_IMPL;
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (link)
|
||||
cahute_close_link(link);
|
||||
if (args.local_source_fp && args.local_source_path)
|
||||
fclose(args.local_source_fp);
|
||||
if (args.local_target_fp && args.local_target_path)
|
||||
fclose(args.local_target_fp);
|
||||
|
||||
switch (err) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_IMPL:
|
||||
fprintf(stderr, "The operation was not implemented yet.\n");
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_TOO_MANY:
|
||||
fprintf(stderr, "Too many found calculators, please only keep one.\n");
|
||||
break;
|
||||
|
||||
case CAHUTE_ERROR_NOT_FOUND:
|
||||
fprintf(stderr, error_notfound);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "An unknown error has occurred.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef XFER9860_H
|
||||
#define XFER9860_H 1
|
||||
#include <cahute.h>
|
||||
|
||||
#define OPERATION_UPLOAD 1
|
||||
#define OPERATION_DOWNLOAD 2
|
||||
#define OPERATION_INFO 3
|
||||
#define OPERATION_OPTIMIZE 4
|
||||
|
||||
/**
|
||||
* Parsed arguments structure.
|
||||
*
|
||||
* The operations are the following:
|
||||
*
|
||||
* - UPLOAD contents of a {local_source_fp} as {distant_target_name} on
|
||||
* storage device "fls0".
|
||||
* - DOWNLOAD contents of {distant_source_name} from storage device "fls0"
|
||||
* into {local_target_fp}.
|
||||
* - Get INFO regarding the calculator.
|
||||
* - OPTIMIZE the "fls0" storage device.
|
||||
*
|
||||
* @property operation Selected operation.
|
||||
* @property throttle Throttle time in seconds.
|
||||
* @property distant_source_name Distant file name for download.
|
||||
* @property distant_target_name Distant file name for upload.
|
||||
* @property local_source_path Path of the local source file for upload.
|
||||
* @property local_target_path Path of the local target file for download.
|
||||
* @property local_source_fp Local source file pointer for upload.
|
||||
* @property local_target_fp Local target file pointer for download.
|
||||
*/
|
||||
struct args {
|
||||
int operation;
|
||||
int throttle;
|
||||
char const *distant_source_name;
|
||||
char const *distant_target_name;
|
||||
char const *local_source_path;
|
||||
char const *local_target_path;
|
||||
FILE *local_source_fp;
|
||||
FILE *local_target_fp;
|
||||
};
|
||||
|
||||
extern int parse_args(int argc, char **argv, struct args *args);
|
||||
|
||||
#endif /* XFER9860_H */
|
|
@ -0,0 +1,243 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#include "xfer9860.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char const about_message[] =
|
||||
"xfer9860 - from Cahute v" CAHUTE_VERSION
|
||||
" (licensed under CeCILL 2.1)\n"
|
||||
"\n"
|
||||
"This utility is a reimplementation of the utility originally made\n"
|
||||
"by Andreas Bertheussen, Manuel Naranjo and Bruno L. Alata in 2007.\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.\n";
|
||||
|
||||
static char const help_message[] =
|
||||
"Usage: %s [-h] [-a] [-t <throttle>] ...\n"
|
||||
"fx-9860G (SD) communication utility.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
" xfer9860 -u <local file path> <file name>\n"
|
||||
" Upload the file as <file name> on the calculator's main\n"
|
||||
" storage device.\n"
|
||||
"\n"
|
||||
" xfer9860 -d <file name> <local file path>\n"
|
||||
" Download the file named <file name> from the calculator's\n"
|
||||
" main storage device.\n"
|
||||
"\n"
|
||||
" xfer9860 -i\n"
|
||||
" Show information about the connected calculator.\n"
|
||||
"\n"
|
||||
" xfer9860 -o\n"
|
||||
" Optimize the calculator's main storage device.\n"
|
||||
"\n"
|
||||
"Available options are:\n"
|
||||
" -h Show this help message and exit.\n"
|
||||
" -a Show the about message and exit.\n"
|
||||
" -t <throttle> Select the throttle in seconds, i.e. maximum\n"
|
||||
" delay between two packets.\n"
|
||||
"\n"
|
||||
"For guides, topics and reference, consult the documentation:\n"
|
||||
" " CAHUTE_URL
|
||||
"\n"
|
||||
"\n"
|
||||
"For reporting issues and vulnerabilities, consult the following guide:\n"
|
||||
" " CAHUTE_ISSUES_URL "\n";
|
||||
|
||||
/**
|
||||
* Short options for getopt().
|
||||
*/
|
||||
static char const *short_options = "hat:u:d:io";
|
||||
|
||||
/**
|
||||
* Parse the command-line parameters into a parsed arguments structure.
|
||||
*
|
||||
* @param argc Argument count.
|
||||
* @param argv Argument values.
|
||||
* @param args Parsed arguments structure to define.
|
||||
* @return 1 if the parameters have been parsed successfully, 0 otherwise.
|
||||
*/
|
||||
int parse_args(int argc, char **argv, struct args *args) {
|
||||
char const *command_path = argv[0];
|
||||
int about = 0, help = 0, multiple_operations = 0;
|
||||
|
||||
args->operation = 0;
|
||||
args->throttle = 0;
|
||||
args->distant_source_name = NULL;
|
||||
args->distant_target_name = NULL;
|
||||
args->local_source_path = NULL;
|
||||
args->local_target_path = NULL;
|
||||
args->local_source_fp = NULL;
|
||||
args->local_target_fp = NULL;
|
||||
|
||||
opterr = 0;
|
||||
while (1) {
|
||||
int option = getopt(argc, argv, short_options);
|
||||
if (option < 0)
|
||||
break;
|
||||
|
||||
switch (option) {
|
||||
case 't':
|
||||
/* Original command used 'atoi()' here. */
|
||||
args->throttle = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
about = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
help = 1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* Upload mode! */
|
||||
if (args->operation)
|
||||
multiple_operations = 1;
|
||||
|
||||
args->operation = OPERATION_UPLOAD;
|
||||
args->distant_target_name = optarg;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
/* Download mode! */
|
||||
if (args->operation)
|
||||
multiple_operations = 1;
|
||||
|
||||
args->operation = OPERATION_DOWNLOAD;
|
||||
args->distant_source_name = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
/* Optimize mode! */
|
||||
if (args->operation)
|
||||
multiple_operations = 1;
|
||||
|
||||
args->operation = OPERATION_OPTIMIZE;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
/* Information mode! */
|
||||
if (args->operation)
|
||||
multiple_operations = 1;
|
||||
|
||||
args->operation = OPERATION_INFO;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* xfer9860 abandons when it receives an unknown option.
|
||||
* We want to display the help message! */
|
||||
help = 1;
|
||||
goto process_params;
|
||||
}
|
||||
}
|
||||
|
||||
process_params:
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (about) {
|
||||
fprintf(stderr, about_message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (multiple_operations || !args->operation)
|
||||
help = 1;
|
||||
else if (args->operation == OPERATION_UPLOAD) {
|
||||
if (argc != 1)
|
||||
help = 1;
|
||||
else
|
||||
args->local_source_path = argv[0];
|
||||
} else if (args->operation == OPERATION_DOWNLOAD) {
|
||||
if (argc != 1)
|
||||
help = 1;
|
||||
else
|
||||
args->local_target_path = argv[0];
|
||||
} else {
|
||||
if (argc != 0)
|
||||
help = 1;
|
||||
}
|
||||
|
||||
if (help) {
|
||||
fprintf(stderr, help_message, command_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args->distant_target_name
|
||||
&& strnlen(args->distant_target_name, 13) > 12) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"The destination filename is too long: %s\n"
|
||||
"Filesystem only supports 12 characters.",
|
||||
args->distant_target_name
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args->distant_source_name
|
||||
&& strnlen(args->distant_source_name, 13) > 12) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"The source filename is too long: %s\n"
|
||||
"Filesystem only supports 12 characters.",
|
||||
args->distant_source_name
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (args->local_source_path) {
|
||||
args->local_source_fp = fopen(args->local_source_path, "rb");
|
||||
if (!args->local_source_fp) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Unable to open file: %s\n",
|
||||
args->local_source_path
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->local_target_path) {
|
||||
args->local_target_fp = fopen(args->local_target_path, "w");
|
||||
if (!args->local_target_fp) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"Unable to open file: %s\n",
|
||||
args->local_target_path
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
# *****************************************************************************
|
||||
# Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
#
|
||||
# This software is governed by the CeCILL 2.1 license under French law and
|
||||
# abiding by the rules of distribution of free software. You can use, modify
|
||||
# and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
# as circulated by CEA, CNRS and INRIA at the following
|
||||
# URL: https://cecill.info
|
||||
#
|
||||
# As a counterpart to the access to the source code and rights to copy, modify
|
||||
# and redistribute granted by the license, users are provided only with a
|
||||
# limited warranty and the software's author, the holder of the economic
|
||||
# rights, and the successive licensors have only limited liability.
|
||||
#
|
||||
# In this respect, the user's attention is drawn to the risks associated with
|
||||
# loading, using, modifying and/or developing or reproducing the software by
|
||||
# the user in light of its specific status of free software, that may mean
|
||||
# that it is complicated to manipulate, and that also therefore means that it
|
||||
# is reserved for developers and experienced professionals having in-depth
|
||||
# computer knowledge. Users are therefore encouraged to load and test the
|
||||
# software's suitability as regards their requirements in conditions enabling
|
||||
# the security of their systems and/or data to be ensured and, more generally,
|
||||
# to use and operate it in the same conditions as regards security.
|
||||
#
|
||||
# The fact that you are presently reading this means that you have had
|
||||
# knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
# *****************************************************************************
|
||||
"""Sphinx plugin to add the "seven-command" reStructuredText directive."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import docutils.nodes as nodes
|
||||
from docutils.parsers.rst import Directive
|
||||
from docutils.parsers.rst.directives import unchanged
|
||||
from docutils.statemachine import StringList
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
|
||||
def ascii_hex(
|
||||
*,
|
||||
size: int,
|
||||
default: int | None = None,
|
||||
) -> Callable[[str | None], int]:
|
||||
"""Convert the argument into an ASCII-HEX number.
|
||||
|
||||
:param size: Size of the expected ASCII-HEX.
|
||||
"""
|
||||
if default is not None and (default < 0 or default >= 2 ** size):
|
||||
raise ValueError(f"default must be between 0 and {2 ** size - 1}")
|
||||
|
||||
def func(argument: str | None) -> int:
|
||||
"""Convert the argument into a short hexadecimal number."""
|
||||
if argument is None:
|
||||
if default is None:
|
||||
raise ValueError("missing value")
|
||||
|
||||
return default
|
||||
|
||||
m = re.fullmatch(
|
||||
r'[0-9A-Za-z]{' + re.escape(str(size)) + '}',
|
||||
argument,
|
||||
)
|
||||
if m is None:
|
||||
raise ValueError(f"expected a {size}-digit hex")
|
||||
|
||||
return int(m.group().upper(), 16)
|
||||
|
||||
return func
|
||||
|
||||
|
||||
class SevenCommandDirective(Directive):
|
||||
"""Directive for documenting a Protocol 7.00 command."""
|
||||
|
||||
has_content = True
|
||||
option_spec = {
|
||||
"code": ascii_hex(size=2),
|
||||
"ow": unchanged,
|
||||
"ow-example": ascii_hex(size=2, default=0),
|
||||
"dt": unchanged,
|
||||
"dt-example": ascii_hex(size=2, default=0),
|
||||
"fs": unchanged,
|
||||
"fs-example": ascii_hex(size=8, default=0),
|
||||
"d1": unchanged,
|
||||
"d1-example": unchanged,
|
||||
"d2": unchanged,
|
||||
"d2-example": unchanged,
|
||||
"d3": unchanged,
|
||||
"d3-example": unchanged,
|
||||
"d4": unchanged,
|
||||
"d4-example": unchanged,
|
||||
"d5": unchanged,
|
||||
"d5-example": unchanged,
|
||||
"d6": unchanged,
|
||||
"d6-example": unchanged,
|
||||
}
|
||||
|
||||
def is_payload_required(self) -> bool:
|
||||
"""Whether at least one field is used for the command."""
|
||||
return bool(
|
||||
self.options.get("ow")
|
||||
or self.options.get("dt")
|
||||
or self.options.get("fs")
|
||||
or self.options.get("d1")
|
||||
or self.options.get("d2")
|
||||
or self.options.get("d3")
|
||||
or self.options.get("d4")
|
||||
or self.options.get("d5")
|
||||
or self.options.get("d6")
|
||||
)
|
||||
|
||||
def get_table(self) -> nodes.table:
|
||||
"""Get the table."""
|
||||
table = nodes.table()
|
||||
table['classes'] += ['colwidths-auto']
|
||||
tgroup = nodes.tgroup(cols=2)
|
||||
table += tgroup
|
||||
|
||||
tbody = nodes.tbody()
|
||||
tgroup += nodes.colspec()
|
||||
tgroup += nodes.colspec()
|
||||
|
||||
def add_entry(name: str, description: str, /) -> None:
|
||||
"""Add an entry to the table."""
|
||||
nonlocal tbody
|
||||
|
||||
row_node = nodes.row()
|
||||
tbody += row_node
|
||||
|
||||
title_entry_node = nodes.entry()
|
||||
desc_entry_node = nodes.entry()
|
||||
row_node += title_entry_node
|
||||
row_node += desc_entry_node
|
||||
|
||||
title = nodes.strong()
|
||||
title += [nodes.Text(name)]
|
||||
title_entry_node += [title]
|
||||
|
||||
self.state.nested_parse(
|
||||
StringList([description]),
|
||||
self.content_offset,
|
||||
desc_entry_node
|
||||
)
|
||||
|
||||
if self.options.get("ow"):
|
||||
add_entry("Overwrite (OW)", self.options["ow"])
|
||||
if self.options.get("dt"):
|
||||
add_entry("Data Type (DT)", self.options["dt"])
|
||||
if self.options.get("fs"):
|
||||
add_entry("Filesize (FS)", self.options["fs"])
|
||||
for k in range(1, 7):
|
||||
if self.options.get(f"d{k}"):
|
||||
add_entry(f"Data {k} (D{k})", self.options[f"d{k}"])
|
||||
|
||||
tgroup += tbody
|
||||
return table
|
||||
|
||||
def get_example(self) -> str:
|
||||
"""Get an example to display."""
|
||||
code = self.options["code"]
|
||||
ow = self.options.get("ow-example") or 0
|
||||
dt = self.options.get("dt-example") or 0
|
||||
fs = self.options.get("fs-example") or 0
|
||||
d1 = self.options.get("d1-example") or ""
|
||||
d2 = self.options.get("d2-example") or ""
|
||||
d3 = self.options.get("d3-example") or ""
|
||||
d4 = self.options.get("d4-example") or ""
|
||||
d5 = self.options.get("d5-example") or ""
|
||||
d6 = self.options.get("d6-example") or ""
|
||||
|
||||
header = "T ST "
|
||||
content = f". {code:02X} "
|
||||
|
||||
if self.is_payload_required():
|
||||
# Compute the unordered string to compute the checksum and the
|
||||
# size of the data.
|
||||
raw_unordered = (
|
||||
f"{ow:02X}{dt:02X}{fs:08X}"
|
||||
+ "".join(f"{len(x):02X}{x}" for x in (d1, d2, d3, d4, d5, d6))
|
||||
)
|
||||
data_size = len(raw_unordered)
|
||||
raw_unordered += f"{code:02X}1{data_size:04X}"
|
||||
|
||||
checksum = (~sum(raw_unordered.encode("ascii")) + 1) & 255
|
||||
|
||||
header += "EX DS OW DT FS "
|
||||
header += " ".join(f"SD{i}" for i in range(1, 7))
|
||||
content += f" 1 {data_size:04X} {ow:02X} {dt:02X} {fs:08X} "
|
||||
content += " ".join(f" {len(x):02X}" for x in (d1, d2, d3, d4, d5, d6))
|
||||
|
||||
for i, x in enumerate((d1, d2, d3, d4, d5, d6)):
|
||||
if not x:
|
||||
continue
|
||||
|
||||
# We need to align the string and the header, even if the string
|
||||
# is only 1 character long.
|
||||
if len(x) == 1:
|
||||
x = " " + x
|
||||
|
||||
header += f" D{i + 1}" + " " * ((len(x) - 2))
|
||||
content += f" {x}"
|
||||
else:
|
||||
header += "EX "
|
||||
content += " 0 "
|
||||
|
||||
checksum = (~sum(f"{code:02X}0".encode("ascii")) + 1) & 255
|
||||
|
||||
header += " CS"
|
||||
content += f" {checksum:02X}"
|
||||
|
||||
return header + "\n" + content
|
||||
|
||||
def run(self) -> list[nodes.Node]:
|
||||
"""Run the directive.
|
||||
|
||||
:return: Produced nodes.
|
||||
"""
|
||||
container = nodes.container()
|
||||
|
||||
if self.is_payload_required():
|
||||
container += self.get_table()
|
||||
|
||||
if self.content:
|
||||
self.state.nested_parse(self.content, self.content_offset, container)
|
||||
|
||||
paragraph_node = nodes.paragraph()
|
||||
container += paragraph_node
|
||||
paragraph_node += [
|
||||
nodes.Text("An example of such command is the following:"),
|
||||
]
|
||||
|
||||
example_node = nodes.literal_block()
|
||||
example_node["language"] = "text"
|
||||
container += example_node
|
||||
example_node += [nodes.Text(self.get_example())]
|
||||
|
||||
return [container]
|
||||
|
||||
|
||||
def setup(app: Sphinx, /) -> None:
|
||||
"""Set up the extension.
|
||||
|
||||
:param app: The Sphinx application to set up the extension for.
|
||||
"""
|
||||
app.add_directive("seven-command", SevenCommandDirective)
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="80" height="80" version="1.1" viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(210 -414.59)">
|
||||
<path class="st0" d="m-143.25 487.96c-37.376-45.16-18.688-22.58 0 0zm-17.694-49.046c3.1042 0.31042 3.725 1.8625 4.0354 3.4146 0.62083 2.4834 0.62083 20.177 0 23.281-0.31042 2.1729-1.8625 3.725-3.725 4.0354-0.93125 0-2.4833 0.31043-3.1042 0.31043v17.694c1.2417 0 4.3458 0 7.1396-0.31042 6.5187-0.93125 11.796-4.6562 13.658-12.727 1.2417-5.5875 1.2417-32.594 0-38.802-1.5521-6.5188-5.5875-12.106-12.417-13.658-6.2083-1.2417-22.35-1.2417-29.179 0-4.9667 0.93125-10.865 5.5875-12.417 13.348-1.2417 7.1396-1.5521 32.283 0 39.112 2.1729 9.0021 10.244 11.796 13.038 12.106 3.1042 0.31042 5.2771 0.31042 6.5188 0.31042v-17.694c-1.2417 0-4.6562 0.31042-5.5875-2.7938-0.62083-1.8625-0.62083-19.246-0.31042-23.592 0.31042-2.1729 1.2417-3.4146 3.4146-3.725 4.3458-0.93125 14.9-0.93125 18.935-0.31042z" fill="#003296"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,19 @@
|
|||
h1 img, h2 img, p img {
|
||||
vertical-align: middle;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.sidebar-logo {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.mermaid {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bottom-of-page .icons svg,
|
||||
.bottom-of-page .icons img {
|
||||
width: auto;
|
||||
height: 2em;
|
||||
vertical-align: middle;
|
||||
}
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="88" height="31" viewBox="0 0 88 31"><g id="Background"><rect width="88" height="31" fill="#1565c0"/></g><g id="_3D"><polygon points="88 0 88 31 0 31 2 29 86 29 86 2 88 0" fill="#263238" opacity=".5"/><polygon points="88 0 86 2 2 2 2 29 0 31 0 0 88 0" fill="#fff" opacity=".5"/></g><g id="Text"><path d="m40.86,9.65c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.21v-3.31c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.22v-5.92h1.22v.68c.4-.48,1.04-.77,1.75-.77.93,0,1.72.4,2.13,1.17.37-.72,1.2-1.17,2.06-1.17,1.39,0,2.44.87,2.44,2.52v3.49h-1.21v-3.31Z" fill="#fff"/><path d="m46.01,6.94c1,0,1.69.47,2.05.96v-.86h1.24v5.92h-1.24v-.88c-.38.5-1.08.98-2.07.98-1.54,0-2.77-1.26-2.77-3.08s1.24-3.03,2.79-3.03Zm.26,1.06c-.91,0-1.79.69-1.79,1.97s.88,2.02,1.79,2.02,1.79-.72,1.79-2-.87-1.99-1.79-1.99Z" fill="#fff"/><path d="m53.3,6.94c.77,0,1.59.37,2.04.92v-2.86h1.24v7.95h-1.24v-.89c-.38.54-1.08.99-2.05.99-1.56,0-2.79-1.26-2.79-3.08s1.24-3.03,2.8-3.03Zm.25,1.06c-.91,0-1.79.69-1.79,1.97s.88,2.02,1.79,2.02,1.79-.72,1.79-2-.87-1.99-1.79-1.99Z" fill="#fff"/><path d="m60.73,13.05c-1.7,0-2.95-1.2-2.95-3.06s1.2-3.05,2.95-3.05,2.88,1.17,2.88,2.91c0,.2-.01.4-.04.6h-4.52c.09.98.78,1.57,1.69,1.57.75,0,1.17-.37,1.4-.83h1.32c-.33,1.03-1.27,1.86-2.72,1.86Zm-1.68-3.59h3.28c-.02-.91-.74-1.49-1.65-1.49-.83,0-1.49.56-1.62,1.49Z" fill="#fff"/><path d="m70.89,6.94c1.57,0,2.78,1.2,2.78,3.03s-1.22,3.08-2.78,3.08c-.98,0-1.68-.44-2.06-.96v.86h-1.22v-7.95h1.22v2.91c.39-.54,1.13-.98,2.06-.98Zm-.27,1.06c-.91,0-1.79.72-1.79,1.99s.88,2,1.79,2,1.8-.74,1.8-2.02-.88-1.97-1.8-1.97Z" fill="#fff"/><path d="m78.95,7.04h1.27l-3.63,8.7h-1.27l1.2-2.88-2.33-5.82h1.36l1.67,4.51,1.73-4.51Z" fill="#fff"/><path d="m34.48,17.94c1,0,1.69.47,2.05.96v-.86h1.24v5.92h-1.24v-.88c-.38.5-1.08.98-2.07.98-1.54,0-2.77-1.26-2.77-3.08s1.24-3.03,2.79-3.03Zm.26,1.06c-.91,0-1.79.69-1.79,1.97s.88,2.02,1.79,2.02,1.79-.72,1.79-2-.87-1.99-1.79-1.99Z" fill="#fff"/><path d="m42.17,16.01h1.22v2.72c.41-.49,1.07-.78,1.84-.78,1.32,0,2.35.87,2.35,2.52v3.49h-1.21v-3.31c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.22v-7.95Z" fill="#fff"/><path d="m54.5,23.96h-1.22v-.71c-.39.5-1.05.79-1.75.79-1.39,0-2.44-.87-2.44-2.52v-3.48h1.21v3.3c0,1.08.59,1.64,1.48,1.64s1.49-.56,1.49-1.64v-3.3h1.22v5.92Z" fill="#fff"/><path d="m64.5,20.65c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.21v-3.31c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.22v-5.92h1.22v.68c.4-.48,1.04-.77,1.75-.77.93,0,1.72.4,2.13,1.17.37-.72,1.2-1.17,2.06-1.17,1.39,0,2.44.87,2.44,2.52v3.49h-1.21v-3.31Z" fill="#fff"/><path d="m69.65,17.94c1,0,1.69.47,2.05.96v-.86h1.24v5.92h-1.24v-.88c-.38.5-1.08.98-2.07.98-1.54,0-2.77-1.26-2.77-3.08s1.24-3.03,2.79-3.03Zm.26,1.06c-.91,0-1.79.69-1.79,1.97s.88,2.02,1.79,2.02,1.79-.72,1.79-2-.87-1.99-1.79-1.99Z" fill="#fff"/><path d="m78.74,20.65c0-1.08-.59-1.64-1.48-1.64s-1.49.56-1.49,1.64v3.31h-1.22v-5.92h1.22v.68c.4-.48,1.05-.77,1.76-.77,1.39,0,2.43.87,2.43,2.52v3.49h-1.21v-3.31Z" fill="#fff"/></g><g id="Image"><circle cx="15.37" cy="15.5" r="10.3" fill="#ffcc80" stroke="#263238" stroke-miterlimit="10" stroke-width="1.5"/><rect x="7.55" y="13.8" width="2.54" height="3.4" rx="1.27" ry="1.27" fill="#263238"/><rect x="20.65" y="13.8" width="2.54" height="3.4" rx="1.27" ry="1.27" fill="#263238"/><path d="m18.44,15.5c0,1.7-1.37,3.07-3.07,3.07s-3.07-1.37-3.07-3.07" fill="none" stroke="#263238" stroke-miterlimit="10" stroke-width="1.5"/></g></svg>
|
After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,240 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="76.994mm" height="17.992mm" version="1.1" viewBox="0 0 76.994 17.992" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image width="76.994" height="17.992" preserveAspectRatio="none" xlink:href="data:image/png;base64,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
|
||||
kf8AIqUGvdlPCQsAAAAASUVORK5CYII=
|
||||
"/></svg>
|
After Width: | Height: | Size: 18 KiB |
|
@ -0,0 +1,53 @@
|
|||
Acknowledgements
|
||||
================
|
||||
|
||||
There have been many projects over the years about reversing and
|
||||
reimplementing CASIO's shenannigans for using their calculators from
|
||||
alternative OSes, or simply for fun or out of curiosity. Cahute couldn't
|
||||
have been made without their research, implementations and in some cases,
|
||||
documentation. This page is a little tribute to these works.
|
||||
|
||||
* Thanks to Tom Wheeley and Tom Lynn for their work on CaS and Caspro_
|
||||
and the `Casio Graphical Calculator Encyclopaedia`_.
|
||||
* Thanks to the (now defunct) Graph100.com wiki, `saved here
|
||||
<Graph100.com Wiki_>`_ for historical purposes.
|
||||
* Thanks to the team behind Casetta_ for their documentation on legacy
|
||||
protocols and file formats, which helped me navigate the subtleties more
|
||||
easily.
|
||||
* Thanks to `Simon Lothar`_ and Andreas Bertheussen for their work on
|
||||
Protocol 7.00 and derivatives through fxReverse_ and xfer9860, and to
|
||||
Teamfx_ for `their additions <Teamfx additions_>`_.
|
||||
* Thanks to the Cemetech community for their `Prizm Wiki`_, especially
|
||||
gbl08ma, BrandonWilson and amazonka.
|
||||
* Thanks to Nessotrin_ for their work on UsbConnector_, which prompted me
|
||||
to work on a better version in the first place.
|
||||
|
||||
There are obviously plenty more people working on other connected aspects
|
||||
(hardware, low-level system stuff), administering or moderating forums and
|
||||
websites, maintaining communication with CASIO and other partners.
|
||||
Quoting you all would take a substantial time, and I'd likely miss quite a lot
|
||||
of you, but thank you all for your efforts!
|
||||
|
||||
.. _Simon Lothar:
|
||||
https://www.casiopeia.net/forum/memberlist.php?mode=viewprofile&u=10405
|
||||
.. _Teamfx:
|
||||
https://www.casiopeia.net/forum/memberlist.php?mode=viewprofile&u=10504&sid=b1f4fb842b29e6f686d832a7e1117789
|
||||
.. _Nessotrin:
|
||||
https://www.planet-casio.com/Fr/compte/voir_profil.php?membre=nessotrin
|
||||
|
||||
.. _Casio Graphical Calculator Encyclopaedia:
|
||||
https://serval.mythic-beasts.com/~tom/calcs/calcs/encyc/
|
||||
.. _Graph100.com Wiki:
|
||||
https://bible.planet-casio.com/cakeisalie5/websaves/graph100.com/
|
||||
.. _fxReverse:
|
||||
https://bible.planet-casio.com/simlo/fxreverse/fxReverse2.pdf
|
||||
.. _Teamfx additions: https://bible.planet-casio.com/teamfx/
|
||||
.. _Prizm Wiki: https://prizm.cemetech.net/
|
||||
.. _UsbConnector:
|
||||
https://www.planet-casio.com/Fr/forums/topic13656-1-usbconnector
|
||||
-remplacement-de-fa124-multi-os.html
|
||||
|
||||
.. _Casetta: https://casetta.tuxfamily.org/
|
||||
.. _Caspro:
|
||||
https://web.archive.org/web/20160504230033/
|
||||
http://www.spiderpixel.co.uk:80/caspro/
|
|
@ -0,0 +1,12 @@
|
|||
Command line reference
|
||||
======================
|
||||
|
||||
This section presents the command line reference, i.e. all options and
|
||||
syntaxes support by Cahute's command-line utilities.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cli/p7
|
||||
cli/p7screen
|
||||
cli/xfer9860
|
|
@ -0,0 +1,391 @@
|
|||
.. _p7:
|
||||
|
||||
``p7`` command line reference
|
||||
=============================
|
||||
|
||||
p7 is a utility originally provided with libp7_ back in August of 2016 by
|
||||
`Thomas Touhey`_. It is used to interact with the calculator's storage
|
||||
devices from any calculator using Protocol 7.00.
|
||||
|
||||
.. warning::
|
||||
|
||||
This interface is provided by compatibility with libp7 / libcasio, and
|
||||
must not be changed to bring new features or change the syntax of
|
||||
existing ones.
|
||||
|
||||
For concrete steps in using p7, consult the following guides:
|
||||
|
||||
* :ref:`guide-cli-send-file`;
|
||||
* :ref:`guide-cli-get-file`;
|
||||
* :ref:`guide-cli-get-info`.
|
||||
|
||||
Available options for all subcommands are the following:
|
||||
|
||||
``-l``, ``--log``
|
||||
Logging level to set the library as, as any of ``info``, ``warning``,
|
||||
``error``, ``fatal``, ``none``.
|
||||
|
||||
This option may allow contributors to visualize the effects of their
|
||||
contribution better, and allows users to produce a full output to join
|
||||
to an issue.
|
||||
|
||||
See :ref:`logging` for more information.
|
||||
|
||||
p7 is used through subcommands that work on a link, with the exception of
|
||||
the ``list-devices`` subcommand. Available options for such subcommands
|
||||
are the following:
|
||||
|
||||
``--com <device>``
|
||||
Path or name of the serial device with which to communicate,
|
||||
e.g. ``/dev/ttyUSB0``.
|
||||
|
||||
If this option is not provided, p7 will look for a calculator connected
|
||||
through USB.
|
||||
|
||||
``--use <settings>``
|
||||
Serial settings to instantiate the serial link with.
|
||||
|
||||
This parameter is of the following format:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
<Speed in bauds><Parity><Stop bits>
|
||||
|
||||
Where:
|
||||
|
||||
* The speed in bauds is expressed as an integer, e.g. ``19200``.
|
||||
* The parity is either ``O`` for odd parity, ``E`` for even parity,
|
||||
and ``N`` if parity checks are disabled altogether.
|
||||
* The stop bits is either ``1`` or ``2``.
|
||||
|
||||
By default, the serial link is instanciated with a speed of 9600 bauds,
|
||||
no parity and 2 stop bits (``9600N2``).
|
||||
|
||||
This option is ignored if the path or name of a serial device is not
|
||||
provided using the ``--com`` option.
|
||||
|
||||
``--set <settings>``
|
||||
Serial settings to negotiate with the calculator.
|
||||
|
||||
The parameter is of the same format as the ``--use`` option described
|
||||
above.
|
||||
|
||||
This option is ignored if the path or name of a serial device is not
|
||||
provided using the ``--com`` option.
|
||||
|
||||
``--reset``
|
||||
Short hand form of ``--set 9600N2``.
|
||||
|
||||
``--no-init``
|
||||
Disable the initiation handshake when the link is opened.
|
||||
|
||||
This is mostly useful if combining multiple consecutive p7 subcommands,
|
||||
if the previous one was passed ``--no-exit``.
|
||||
|
||||
``--no-exit``
|
||||
Disable the termination handshake when the link is closed.
|
||||
|
||||
This is mostly useful if combining multiple consecutive p7 subcommands,
|
||||
provided the next one is passed ``--no-init``.
|
||||
|
||||
Invalid options are ignored by p7. If an option is provided several time,
|
||||
only the latest occurrence will be taken into account.
|
||||
|
||||
See the following sections for subcommand specification.
|
||||
|
||||
.. _p7-list-devices:
|
||||
|
||||
``list-devices`` subcommand reference
|
||||
-------------------------------------
|
||||
|
||||
This subcommand is used to list serial devices available to be used by p7.
|
||||
|
||||
This subcommand does not provide additional options.
|
||||
|
||||
An example execution is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ p7 list-devices
|
||||
Available devices:
|
||||
|
||||
- /dev/ttyUSB1
|
||||
- /dev/ttyUSB2
|
||||
|
||||
.. _p7-info:
|
||||
|
||||
``info`` subcommand reference
|
||||
-----------------------------
|
||||
|
||||
This subcommand is used to get information regarding a calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 info
|
||||
|
||||
.. _p7-idle:
|
||||
|
||||
``idle`` subcommand reference
|
||||
-----------------------------
|
||||
|
||||
This subcommand does not run any use case, and is used to only initiate,
|
||||
terminate, and/or update serial parameters on a link, when chaining multiple
|
||||
commands.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 idle
|
||||
|
||||
.. _p7-send:
|
||||
|
||||
``send`` subcommand reference
|
||||
-----------------------------
|
||||
|
||||
This subcommand is used for sending a file to a storage device on the
|
||||
calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 send [options...] <local file path>
|
||||
|
||||
Where the local file path is the path to the local file to send, relative
|
||||
to the working directory; for example, ``myaddin.g1a``.
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-#``
|
||||
Flag to enable displaying of a loading bar to show transfer progress.
|
||||
|
||||
``-f``, ``--force``
|
||||
If the file already exists in the calculator's device storage, force
|
||||
overwriting it or not.
|
||||
|
||||
By default, if the case occurs, the subcommand requests an interactive
|
||||
overwrite confirmation or rejection.
|
||||
|
||||
``-o``, ``--output``
|
||||
File name the file should be stored as on the storage device,
|
||||
e.g. ``-o MYADDIN.G1A``.
|
||||
|
||||
By default, the output file name is determined using the base name
|
||||
of the local path.
|
||||
|
||||
``-d``, ``--directory``
|
||||
Directory name in which the file should be sent to.
|
||||
|
||||
By default, the file is sent to the storage device's root.
|
||||
|
||||
``--storage``
|
||||
Name of the storage device on which the file should be stored.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-get:
|
||||
|
||||
``get`` subcommand reference
|
||||
----------------------------
|
||||
|
||||
This command is used to request a file from a storage device on the
|
||||
calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 get [options...] <distant file name>
|
||||
|
||||
Where the distant file name is the name of the file on the calculator.
|
||||
|
||||
.. warning::
|
||||
|
||||
Note that the parameter is **NOT** the path of the file, but the name
|
||||
of the file. If you wish to request a file from a directory, you must
|
||||
use the ``-d`` or ``--directory`` option.
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-#``
|
||||
Flag to enable displaying of a loading bar to show transfer progress.
|
||||
|
||||
``-o``, ``--output``
|
||||
Local path of the file to which to write the result, absolute or relative
|
||||
to the working directory.
|
||||
|
||||
If the file already exists, it will be overwritten automatically.
|
||||
|
||||
By default, this is set to the distant file name in the current working
|
||||
directory.
|
||||
|
||||
``-d``, ``--directory``
|
||||
Name of the distant directory in which the requested file is present.
|
||||
|
||||
By default, the file is requested from the storage device's root.
|
||||
|
||||
``--storage``
|
||||
Name of the storage device from which the file should be requested.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-copy:
|
||||
|
||||
``copy`` subcommand reference
|
||||
-----------------------------
|
||||
|
||||
This subcommand is used to copy a distant file to another on a storage device
|
||||
on the calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 copy [options...] <source file name> <target file name>
|
||||
|
||||
.. warning::
|
||||
|
||||
Both parameters are **NOT** the file paths, but the file names.
|
||||
|
||||
If you wish to set a directory for the source file, use the ``-d``
|
||||
or ``--directory`` option.
|
||||
|
||||
If you wish to set a directory for the target file, use the ``-t``
|
||||
or ``--to`` option.
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-d``, ``--directory``
|
||||
Directory in which the source file should be retrieved from.
|
||||
|
||||
By default, the source file is retrieved from the storage device's root.
|
||||
|
||||
``-t``, ``--to``
|
||||
Directory in which the target file should be created in.
|
||||
|
||||
By default, the target file is created in the storage device's root.
|
||||
|
||||
``--storage``
|
||||
Name of the storage device on which the copy should occur.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-delete:
|
||||
|
||||
``delete`` subcommand reference
|
||||
-------------------------------
|
||||
|
||||
This subcommand is used to delete a distant file on a storage device on
|
||||
the calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 delete [options...] <distant file name>
|
||||
|
||||
.. warning::
|
||||
|
||||
Note that the parameter is **NOT** the path of the file, but the name
|
||||
of the file. If you wish to request a file from a directory, you must
|
||||
use the ``-d`` or ``--directory`` option.
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-d``, ``--directory``
|
||||
Directory in which the file should be deleted from.
|
||||
|
||||
By default, the file is deleted from the storage device's root.
|
||||
|
||||
``--storage``
|
||||
Name of the storage device on which the deletion should occur.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-list:
|
||||
|
||||
``list`` subcommand reference
|
||||
-----------------------------
|
||||
|
||||
This subcommand is used to list files present on a storage device on
|
||||
the calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 list [options...]
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-d``, ``--directory``
|
||||
Directory in which the file should be listed in.
|
||||
|
||||
By default, this subcommand lists files from all directories, including
|
||||
the storage device's root.
|
||||
|
||||
``--storage``
|
||||
Name of the storage device on which to list files.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-reset:
|
||||
|
||||
``reset`` subcommand reference
|
||||
------------------------------
|
||||
|
||||
This subcommand is used to reset a storage device on the calculator.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 reset [options...]
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``--storage``
|
||||
Name of the storage device to reset.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _p7-optimize:
|
||||
|
||||
``optimize`` subcommand reference
|
||||
---------------------------------
|
||||
|
||||
This subcommand is used to optimize a storage device on the calculator,
|
||||
i.e. defragment in order to save space.
|
||||
|
||||
The syntax is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
p7 optimize [options...]
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``--storage``
|
||||
Name of the storage device to optimize.
|
||||
|
||||
By default, this is set to ``fls0`` (flash memory filesystem).
|
||||
However, this can be set to other storage device names, such as
|
||||
``crd0`` (SD card) for calculators with an SD card slot.
|
||||
|
||||
.. _libp7: https://p7.planet-casio.com/
|
||||
.. _Thomas Touhey: https://thomas.touhey.fr/
|
|
@ -0,0 +1,42 @@
|
|||
.. _p7screen:
|
||||
|
||||
``p7screen`` command line reference
|
||||
===================================
|
||||
|
||||
p7screen is a utility originally provided with libp7_ back in
|
||||
September of 2016 by `Thomas Touhey`_. It is used for receiving the
|
||||
screen from any USB calculator in "Projector", "Screen Capture" or
|
||||
"Screen Receiver" mode, and displaying it to a basic window using SDL_.
|
||||
|
||||
.. warning::
|
||||
|
||||
This interface is provided by compatibility with libp7 / libcasio, and
|
||||
must not be changed to bring new features or change the syntax of existing
|
||||
ones.
|
||||
|
||||
For concrete steps on using p7screen, see :ref:`guide-cli-display-screen`.
|
||||
|
||||
Available options are the following:
|
||||
|
||||
``-z``, ``--zoom``
|
||||
Zoom, as an integer from 1 to 16.
|
||||
|
||||
Having a zoom of N means that a single pixel on the calculator
|
||||
will be displayed as an NxN full square on the host.
|
||||
|
||||
``-l``, ``--log``
|
||||
Logging level to set the library as, as any of ``info``, ``warning``,
|
||||
``error``, ``fatal``, ``none``.
|
||||
|
||||
This option may allow contributors to visualize the effects of their
|
||||
contribution better, and allows users to produce a full output to join
|
||||
to an issue.
|
||||
|
||||
See :ref:`logging` for more information.
|
||||
|
||||
Invalid options are ignored by p7screen. If an option is provided several time,
|
||||
only the latest occurrence will be taken into account.
|
||||
|
||||
.. _libp7: https://p7.planet-casio.com/
|
||||
.. _Thomas Touhey: https://thomas.touhey.fr/
|
||||
.. _SDL: https://www.libsdl.org/
|
|
@ -0,0 +1,47 @@
|
|||
.. _xfer9860:
|
||||
|
||||
``xfer9860`` command line reference
|
||||
===================================
|
||||
|
||||
`xfer9860 <xfer9860 project page_>`_ is a tool originally released back in
|
||||
June 2007 by Andreas Bertheussen for their fx-9860G SD. It is used to interact
|
||||
with the calculator's storage memory from any calculator supporting
|
||||
Protocol 7.00.
|
||||
|
||||
.. warning::
|
||||
|
||||
This interface is provided by compatibility with Andres Bertheussen's
|
||||
work, and must not be changed to bring new features or change the syntax of
|
||||
existing ones.
|
||||
|
||||
The utility operates differently depending on the provided option:
|
||||
|
||||
``xfer9860 -u <local file path> <file name>``
|
||||
**U**\ pload the file as ``<file name>`` on the calculator's main
|
||||
storage device.
|
||||
|
||||
``xfer9860 -d <file name> <local file path>``
|
||||
**D**\ ownload the file named ``<file name>`` on the calculator's main
|
||||
storage device.
|
||||
|
||||
``xfer9860 -i``
|
||||
Gather **i**\ nformation regarding the calculator.
|
||||
|
||||
``xfer9860 -o``
|
||||
**O**\ ptimize the calculator's main storage device.
|
||||
|
||||
Available options for all operations are the following:
|
||||
|
||||
``-h``, ``-a``
|
||||
Display the help message and exit.
|
||||
|
||||
``-a`` actually stands for "**a**\ bout", and only displayed licensing
|
||||
information while ``-h`` stands for "**h**\ elp" and only displayed
|
||||
usage help.
|
||||
|
||||
Cahute's implementation shows the same message for both options.
|
||||
|
||||
``-t``
|
||||
**T**\ hrottle in seconds, i.e. delay in milliseconds between packets.
|
||||
|
||||
.. _xfer9860 project page: https://sourceforge.net/projects/xfer9860/
|
|
@ -0,0 +1,118 @@
|
|||
"""Configuration file for the Sphinx documentation builder.
|
||||
|
||||
For the full list of built-in configuration values, see the documentation:
|
||||
https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent / "_ext"))
|
||||
|
||||
project = "Cahute"
|
||||
version = "0.1"
|
||||
copyright = "2024, Thomas Touhey"
|
||||
author = "Thomas Touhey"
|
||||
|
||||
extensions = [
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinxcontrib.mermaid",
|
||||
"add_seven_command_directive",
|
||||
]
|
||||
|
||||
templates_path: list[str] = []
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
primary_domain = "c"
|
||||
|
||||
html_theme = "furo"
|
||||
html_theme_options = {
|
||||
"footer_icons": [
|
||||
{
|
||||
"name": "Planète Casio",
|
||||
"url": "https://www.planet-casio.com/Fr/",
|
||||
"html": (Path("_static") / "planete_casio.svg").open().read(),
|
||||
"class": ""
|
||||
},
|
||||
{
|
||||
"name": "Made by a Human",
|
||||
"url": "/project.html",
|
||||
"html": (Path("_static") / "made_by_a_human.svg").open().read(),
|
||||
"class": "",
|
||||
},
|
||||
],
|
||||
}
|
||||
html_static_path = ["_static"]
|
||||
html_title = f"Cahute {version}"
|
||||
html_favicon = '_static/favicon.png'
|
||||
html_logo = '_static/cahute.svg'
|
||||
html_use_index = False
|
||||
html_copy_source = False
|
||||
html_show_sourcelink = False
|
||||
html_domain_indices = False
|
||||
html_css_files = ["custom.css"]
|
||||
|
||||
intersphinx_mapping = {}
|
||||
|
||||
todo_include_todos = True
|
||||
|
||||
mermaid_output_format = "raw"
|
||||
mermaid_init_js = """
|
||||
function isDarkMode() {
|
||||
const color = (
|
||||
getComputedStyle(document.body)
|
||||
.getPropertyValue("--color-foreground-primary")
|
||||
);
|
||||
|
||||
if (color == "#ffffffcc")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function initializeMermaid(isStart) {
|
||||
mermaid.initialize({
|
||||
startOnLoad: isStart,
|
||||
theme: isDarkMode() ? "dark" : "base",
|
||||
darkMode: isDarkMode(),
|
||||
securityLevel: "antiscript"
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
if (
|
||||
mutation.type != "attributes"
|
||||
|| mutation.attributeName != "data-theme"
|
||||
)
|
||||
return
|
||||
|
||||
const nodes = document.querySelectorAll(".mermaid");
|
||||
nodes.forEach(node => {
|
||||
/* Restore the original code before reprocessing. */
|
||||
node.innerHTML = node.getAttribute("data-original-code");
|
||||
|
||||
/* Remove the attribute saying data is processed; it is not! */
|
||||
if (node.hasAttribute("data-processed"))
|
||||
node.removeAttribute("data-processed");
|
||||
});
|
||||
|
||||
initializeMermaid(false);
|
||||
mermaid.run({nodes: nodes, querySelector: ".mermaid"});
|
||||
});
|
||||
});
|
||||
|
||||
(function (window) {
|
||||
/* Store original code for diagrams into an attribute directly, since
|
||||
Mermaid actually completely replaces the content and removes the
|
||||
original code. */
|
||||
document.querySelectorAll(".mermaid").forEach(node => {
|
||||
node.setAttribute("data-original-code", node.innerHTML);
|
||||
})
|
||||
|
||||
initializeMermaid(true);
|
||||
observer.observe(document.body, {attributes: true});
|
||||
})(window);
|
||||
"""
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,14 @@
|
|||
Guides
|
||||
======
|
||||
|
||||
This section consists of multiple guides for solving specific problems.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
guides/install
|
||||
guides/cli
|
||||
guides/developer
|
||||
guides/report
|
||||
guides/package
|
||||
guides/contribute
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="211.66" height="211.66" version="1.0" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-34.777,-129.8)">
|
||||
<g transform="matrix(.87464 0 0 .87464 14.731 23.409)" fill="#1793d1">
|
||||
<path d="m143.89 121.65c-10.773 26.408-17.271 43.681-29.266 69.304 7.3541 7.7938 16.381 16.87 31.04 27.121-15.76-6.484-26.512-12.993-34.544-19.748-15.35 32.025-39.4 77.644-88.206 165.31 38.36-22.142 68.095-35.791 95.807-41-1.19-5.117-1.8665-10.652-1.8206-16.427l0.0455-1.2286c0.60867-24.57 13.393-43.465 28.537-42.183 15.144 1.2829 26.915 22.254 26.306 46.824-0.11452 4.6234-0.63609 9.0711-1.5475 13.196 27.411 5.361 56.828 18.977 94.669 40.818-7.4614-13.735-14.121-26.114-20.481-37.905-10.018-7.7631-20.467-17.866-41.781-28.805 14.651 3.806 25.14 8.1972 33.316 13.105-64.664-120.37-69.9-136.36-92.074-188.39z" fill-rule="evenodd" stroke-width="1.2737"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 919 B |
|
@ -0,0 +1,13 @@
|
|||
As a CLI user, I want to...
|
||||
===========================
|
||||
|
||||
These sections describe specific problems that you may want to solve using
|
||||
the command-line (CLI) utilities provided by Cahute.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cli/get-info
|
||||
cli/send-file
|
||||
cli/get-file
|
||||
cli/display-screen
|
After Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1,34 @@
|
|||
.. _guide-cli-display-screen:
|
||||
|
||||
As a CLI user, I want to display the screen from my calculator
|
||||
==============================================================
|
||||
|
||||
.. warning::
|
||||
|
||||
This guide only works for calculators connected by USB. If you are using
|
||||
a serial link, no option is available to you with Cahute yet!
|
||||
|
||||
In order to display the screen from a CASIO calculator, the steps are the
|
||||
following:
|
||||
|
||||
1. Connect the calculator to the PC using a USB cable.
|
||||
2. Select a screenstreaming mode on the USB calculator.
|
||||
3. Run ``p7screen``.
|
||||
|
||||
Once the calculator is connected, a prompt with various protocols is displayed:
|
||||
|
||||
* On fx9860G and compatible (monochrome calculators), select
|
||||
``Projector`` (F3).
|
||||
* On fx-CG and compatible (color calculators), select
|
||||
``ScreenR(XP)`` (F3) or, if it not available, any mode between
|
||||
``Projector`` (F4) or ``ScreenRecv`` (F2).
|
||||
|
||||
Once this is done, in a terminal, run the following command::
|
||||
|
||||
p7screen
|
||||
|
||||
.. figure:: display-screen.png
|
||||
|
||||
p7screen displaying the screen from a Graph 90+E in ``ScreenR(XP)`` mode.
|
||||
|
||||
For more options, see :ref:`p7screen`.
|
|
@ -0,0 +1,72 @@
|
|||
.. _guide-cli-get-file:
|
||||
|
||||
As a CLI user, I want to get a file from the calculator's storage memory
|
||||
========================================================================
|
||||
|
||||
.. warning::
|
||||
|
||||
This guide is currently only available for fx-9860G and compatible
|
||||
calculators, excluding the fx-CG line of calculators, which need to
|
||||
be used as a normal storage device ("USB Key" mode).
|
||||
|
||||
In this guide, we will assume you want to transfer the ``MYADDIN.G1A`` file
|
||||
from your calculator.
|
||||
|
||||
The instructions vary depending on the way your calculator is connected,
|
||||
see the correct section for your case.
|
||||
|
||||
For more options, see :ref:`p7` and :ref:`p7-get`.
|
||||
|
||||
If you are using USB
|
||||
--------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a mini USB cable.
|
||||
2. Select the ``DataTrans`` (``TransfDon`` in French) mode when prompted.
|
||||
3. Run the transfer from the PC using ``p7 get``.
|
||||
|
||||
Once steps 1 and 2 are done, run the following command::
|
||||
|
||||
p7 get MYADDIN.G1A
|
||||
|
||||
The file should have been successfully transferred from the calculator!
|
||||
|
||||
If you are using serial
|
||||
-----------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a USB to serial cable.
|
||||
2. Configure the calculator to use serial and data transfer, and place
|
||||
the calculator in standby mode.
|
||||
3. Find out which serial port your calculator is connected on.
|
||||
4. Run the transfer from the PC using ``p7 get``.
|
||||
|
||||
For step 2, go to your link application, and do the following:
|
||||
|
||||
* If a ``CABL`` (F4) submenu is available, go into it and press F2
|
||||
to select "3-pin" ("3 broches" in French);
|
||||
* Go to the ``CAPT`` (F6) submenu and press F1 to select "Memory"
|
||||
("Mémoire" in French).
|
||||
* Place your calculator in receiving mode by pressing F2 to select the
|
||||
``RECV`` submenu.
|
||||
|
||||
For step 3, you must run the following command to discover all available
|
||||
serial ports p7 can use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 list-devices
|
||||
|
||||
Unfortunately, if there are several ports, there is no easy way to
|
||||
find out which port is the right one to use; you will need to try
|
||||
each of them.
|
||||
|
||||
For step 4, you can run the transfer by using the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 --com <your-serial-device> get MYADDIN.G1A
|
||||
|
||||
The file should have been successfully transferred from the calculator!
|
|
@ -0,0 +1,69 @@
|
|||
.. _guide-cli-get-info:
|
||||
|
||||
As a CLI user, I want to get information regarding my calculator
|
||||
================================================================
|
||||
|
||||
.. warning::
|
||||
|
||||
This guide is currently only available for fx-9860G and compatible
|
||||
calculators, excluding the fx-CG line of calculators, which need to
|
||||
be used as a normal storage device ("USB Key" mode).
|
||||
|
||||
The instructions vary depending on the way your calculator is connected,
|
||||
see the correct section for your case.
|
||||
|
||||
For more options, see :ref:`p7` and :ref:`p7-info`.
|
||||
|
||||
If you are using USB
|
||||
--------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a mini USB cable.
|
||||
2. Select the ``DataTrans`` (``TransfDon`` in French) mode when prompted.
|
||||
3. Run the command from the PC using ``p7 info``.
|
||||
|
||||
Once steps 1 and 2 are done, run the following command::
|
||||
|
||||
p7 info
|
||||
|
||||
Your calculator's information should have been gathered and displayed!
|
||||
|
||||
If you are using serial
|
||||
-----------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a USB to serial cable.
|
||||
2. Configure the calculator to use serial and data transfer, and place
|
||||
the calculator in standby mode.
|
||||
3. Find out which serial port your calculator is connected on.
|
||||
4. Run the command from the PC using ``p7 info``.
|
||||
|
||||
For step 2, go to your link application, and do the following:
|
||||
|
||||
* If a ``CABL`` (F4) submenu is available, go into it and press F2
|
||||
to select "3-pin" ("3 broches" in French);
|
||||
* Go to the ``CAPT`` (F6) submenu and press F1 to select "Memory"
|
||||
("Mémoire" in French).
|
||||
* Place your calculator in receiving mode by pressing F2 to select the
|
||||
``RECV`` submenu.
|
||||
|
||||
For step 3, you must run the following command to discover all available
|
||||
serial ports p7 can use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 list-devices
|
||||
|
||||
Unfortunately, if there are several ports, there is no easy way to
|
||||
find out which port is the right one to use; you will need to try
|
||||
each of them.
|
||||
|
||||
For step 4, you can run the transfer by using the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 --com <your-serial-device> info
|
||||
|
||||
Your calculator's information should have been gathered and displayed!
|
|
@ -0,0 +1,84 @@
|
|||
.. _guide-cli-send-file:
|
||||
|
||||
As a CLI user, I want to send a file to the calculator's storage memory
|
||||
=======================================================================
|
||||
|
||||
.. warning::
|
||||
|
||||
This guide is currently only available for fx-9860G and compatible
|
||||
calculators, excluding the fx-CG line of calculators, which need to
|
||||
be used as a normal storage device ("USB Key" mode).
|
||||
|
||||
In this guide, we will assume you want to transfer the ``MYADDIN.G1A`` file
|
||||
from your PC to your calculator.
|
||||
|
||||
The instructions vary depending on the way your calculator is connected,
|
||||
see the correct section for your case.
|
||||
|
||||
For more options, see :ref:`p7` and :ref:`p7-send`.
|
||||
|
||||
If you are using USB
|
||||
--------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a mini USB cable.
|
||||
2. Select the ``DataTrans`` (``TransfDon`` in French) mode when prompted.
|
||||
3. Run the transfer from the PC using ``p7 send``.
|
||||
|
||||
Once steps 1 and 2 are done, run the following command::
|
||||
|
||||
p7 send MYADDIN.G1A
|
||||
|
||||
If the file already exists, you will be prompted on whether you want to
|
||||
overwrite the file on the calculator. In this case, you can either:
|
||||
|
||||
* Enter ``y`` and press enter, to confirm the overwrite.
|
||||
* Enter ``n`` and press enter, to reject the overwrite.
|
||||
|
||||
Your file has successfully been transferred to the calculator!
|
||||
|
||||
If you are using serial
|
||||
-----------------------
|
||||
|
||||
The steps are the following:
|
||||
|
||||
1. Connect the calculator to the PC using a USB to serial cable.
|
||||
2. Configure the calculator to use serial and data transfer, and place
|
||||
the calculator in standby mode.
|
||||
3. Find out which serial port your calculator is connected on.
|
||||
4. Run the transfer from the PC using ``p7 send``.
|
||||
|
||||
For step 2, go to your link application, and do the following:
|
||||
|
||||
* If a ``CABL`` (F4) submenu is available, go into it and press F2
|
||||
to select "3-pin" ("3 broches" in French);
|
||||
* Go to the ``CAPT`` (F6) submenu and press F1 to select "Memory"
|
||||
("Mémoire" in French).
|
||||
* Place your calculator in receiving mode by pressing F2 to select the
|
||||
``RECV`` submenu.
|
||||
|
||||
For step 3, you must run the following command to discover all available
|
||||
serial ports p7 can use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 list-devices
|
||||
|
||||
Unfortunately, if there are several ports, there is no easy way to
|
||||
find out which port is the right one to use; you will need to try
|
||||
each of them.
|
||||
|
||||
For step 4, you can run the transfer by using the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
p7 --com <your-serial-device> send MYADDIN.G1A
|
||||
|
||||
If the file already exists, you will be prompted on whether you want to
|
||||
overwrite the file on the calculator. In this case, you can either:
|
||||
|
||||
* Enter ``y`` and press enter, to confirm the overwrite.
|
||||
* Enter ``n`` and press enter, to reject the overwrite.
|
||||
|
||||
Your file has successfully been transferred to the calculator!
|
|
@ -0,0 +1,88 @@
|
|||
Contributing to Cahute
|
||||
======================
|
||||
|
||||
You have something to contribute to Cahute, whether it's a new feature, a tweak
|
||||
on an existing protocol, an unhandled file format, some more background on
|
||||
a feature or problematic, or a fix to a typo in the documentation?
|
||||
|
||||
First of all, thank you so much! This guide will help you set up for efficient
|
||||
contribution, and save some time to all involved.
|
||||
|
||||
.. note::
|
||||
|
||||
If you are interested in the rationale of what is indicated here,
|
||||
you can consult the :ref:`contribution-style` for more information.
|
||||
|
||||
Preparing the repository
|
||||
------------------------
|
||||
|
||||
You must fork Cahute's repository, by:
|
||||
|
||||
* Creating an account on `Gitlab.com`_.
|
||||
* Going on the Cahute repository and selecting "Fork".
|
||||
* Cloning the fork on your PC, by running a command resembling
|
||||
``git clone https://gitlab.com/cahuteproject/cahute.git``.
|
||||
* Changing the current branch to a work branch, by e.g.
|
||||
running ``git switch -c feat/your-goal-here``.
|
||||
|
||||
Installing and setting up the required tools
|
||||
--------------------------------------------
|
||||
|
||||
You will need the following dependencies and tools:
|
||||
|
||||
* Build dependencies for the project; see :ref:`build-cahute`.
|
||||
* Python >= 3.11, with dependencies listed in ``docs/requirements.txt``,
|
||||
which you can either install externally, with a virtualenv or directly,
|
||||
using ``pip install -r docs/requirements.txt``.
|
||||
* `pre-commit`_.
|
||||
|
||||
In order to set up pre-commit, you need to run the following command::
|
||||
|
||||
pre-commit install
|
||||
|
||||
If you are modifying the code, even just when fixing a typo, you need to
|
||||
build the project from the modified source; see :ref:`build-cahute` for
|
||||
more information.
|
||||
|
||||
Testing your changes
|
||||
--------------------
|
||||
|
||||
If you have only updated the documentation, you can run
|
||||
``make -C docs preview``, which will run a webserver on
|
||||
``http://localhost:8000`` to allow you to preview your changes.
|
||||
|
||||
If you have updated the code, you must build the project, then run
|
||||
either ``./p7 <your command args here...>``,
|
||||
``./p7screen <your command args here...>``, or any other custom
|
||||
executable you link with the built ``./libcahute.a`` to test it.
|
||||
|
||||
.. note::
|
||||
|
||||
It is recommended to describe the tests that you have done in the
|
||||
description of the merge request, so that the maintainers can have
|
||||
an idea of what you could have missed!
|
||||
|
||||
Pushing your changes
|
||||
--------------------
|
||||
|
||||
Once you are done, you must commit and push your changes.
|
||||
|
||||
To create your commit, you most certainly want to do something like
|
||||
``git add .``, then ``git commit -m "your message here"``.
|
||||
Note that the message must be formatted a certain way:
|
||||
|
||||
* If you are adding a feature: ``feat: your message here``, e.g.
|
||||
``feat: add hypertriangulation to protocol delta``.
|
||||
* If you are fixing a bug in the code: ``fix: your message here``, e.g.
|
||||
``fix: fix bad buffer usage by TYPKZ OHP packets``.
|
||||
* If you are adding something to or fixing something in the docs:
|
||||
``docs: your message here``, e.g.
|
||||
``docs: add missing section for hypertriangulation flow``.
|
||||
|
||||
You can now push to your repository using
|
||||
``git push -u origin feat/your-goal-here`` (*replace the branch name*).
|
||||
Gitlab will provide you the link to create the merge request.
|
||||
|
||||
.. _Gitlab.com: https://gitlab.com/
|
||||
.. _pre-commit: https://pre-commit.com/
|
||||
.. _Sphinx: https://www.sphinx-doc.org/en/master/
|
|
@ -0,0 +1,13 @@
|
|||
As a developer, I want to...
|
||||
============================
|
||||
|
||||
These sections describe specific problems that you may want to solve using
|
||||
the Cahute C library directly.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
developer/build
|
||||
developer/detect-usb
|
||||
developer/detect-serial
|
||||
developer/open-usb-link
|
|
@ -0,0 +1,50 @@
|
|||
As a developer, I want to use the Cahute library in my project
|
||||
==============================================================
|
||||
|
||||
.. warning::
|
||||
|
||||
This guide assumes that you have already installed the Cahute library.
|
||||
If you have not, see :ref:`guide-install`.
|
||||
|
||||
The instructions to build your project using the Cahute library depend on
|
||||
your build system; please read the correct section for yours!
|
||||
|
||||
Using |cmake| CMake
|
||||
-------------------
|
||||
|
||||
If your project is built using CMake, you can add the following to your
|
||||
``CMakeLists.txt`` file, before defining your targets, to include and start
|
||||
building with Cahute:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
pkg_check_modules(cahute REQUIRED cahute IMPORTED_TARGET)
|
||||
link_libraries(PkgConfig::cahute)
|
||||
|
||||
Using pkg-config
|
||||
----------------
|
||||
|
||||
Cahute defines the ``cahute`` pkg-config configuration. Therefore:
|
||||
|
||||
* You can obtain the compilation flags by running the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pkg-config cahute --cflags
|
||||
|
||||
* You can obtain the linking flags by running the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pkg-config cahute --libs
|
||||
|
||||
For example, if you want to compile a simple project using Cahute, you can
|
||||
use the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cc main.c -o ./my_util `pkg-config cahute --cflags --libs`
|
||||
|
||||
.. |cmake| image:: cmake.svg
|
||||
|
||||
.. _CMake: https://cmake.org/
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 64 63.999998"
|
||||
xml:space="preserve"
|
||||
version="1.1"
|
||||
id="svg39"
|
||||
sodipodi:docname="cmake-icon.svg"
|
||||
width="64"
|
||||
height="64"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><defs
|
||||
id="defs43"> </defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
id="namedview41"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.4266285"
|
||||
inkscape:cx="69.849998"
|
||||
inkscape:cy="22.700001"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg39" /> <style
|
||||
type="text/css"
|
||||
id="style2"> .st0{fill:#064F8C;} .st1{fill:#249847;} .st2{fill:#BE2128;} .st3{fill:#172C36;} .st4{fill:#CDCDCE;} </style> <g
|
||||
id="Layer_2"
|
||||
transform="translate(0,18.599998)"> </g> <g
|
||||
id="g922"
|
||||
transform="matrix(2.2190473,0,0,2.2190473,-14.603456,-34.571419)"><polygon
|
||||
transform="matrix(0.79452357,0,0,0.79452357,3.8001251,12.63966)"
|
||||
class="st0"
|
||||
points="21.3,3.8 3.6,38.8 22.9,22.4 "
|
||||
id="polygon6"
|
||||
style="fill:#064f8c" /><polygon
|
||||
transform="matrix(0.79452357,0,0,0.79452357,3.8001251,12.63966)"
|
||||
class="st1"
|
||||
points="38.6,39.9 14.8,30.3 3.5,39.9 "
|
||||
id="polygon8"
|
||||
style="fill:#249847" /><polygon
|
||||
transform="matrix(0.79452357,0,0,0.79452357,3.8001251,12.63966)"
|
||||
class="st2"
|
||||
points="39.8,39.6 22.1,4.4 24.7,33.5 "
|
||||
id="polygon10"
|
||||
style="fill:#be2128" /><polygon
|
||||
transform="matrix(0.79452357,0,0,0.79452357,3.8001251,12.63966)"
|
||||
style="fill:#cdcdce"
|
||||
id="polygon34"
|
||||
points="23.9,33.2 23,23.3 15.4,29.8 "
|
||||
class="st4" /></g> </svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,21 @@
|
|||
/* Compile using: gcc detect-serial.c `pkg-config cahute --cflags --libs`. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cahute.h>
|
||||
|
||||
int my_callback(void *cookie, cahute_serial_detection_entry const *entry) {
|
||||
printf("New entry data:\n");
|
||||
printf("- %s\n", entry->cahute_serial_detection_entry_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int err;
|
||||
|
||||
err = cahute_detect_serial(&my_callback, NULL);
|
||||
if (err)
|
||||
fprintf(stderr, "Cahute has returned error 0x%04X.\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
.. _guide-developer-detect-serial:
|
||||
|
||||
As a developer, I want to list available serial ports
|
||||
=====================================================
|
||||
|
||||
In order to list calculators connected by USB, you must use
|
||||
:c:func:`cahute_detect_serial`, while providing it with a callback to either
|
||||
add the USB device to your list or display it.
|
||||
|
||||
An example program using this function is the following:
|
||||
|
||||
.. literalinclude:: detect-serial.c
|
||||
:language: c
|
||||
|
||||
An example output for this program is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
New entry data:
|
||||
- Path: /dev/ttyUSB0
|
|
@ -0,0 +1,41 @@
|
|||
/* Compile using: gcc detect-usb.c `pkg-config cahute --cflags --libs`. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cahute.h>
|
||||
|
||||
int my_callback(void *cookie, cahute_usb_detection_entry const *entry) {
|
||||
char const *type_name;
|
||||
|
||||
switch (entry->cahute_usb_detection_entry_type) {
|
||||
case CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN:
|
||||
type_name = "fx-9860G or compatible";
|
||||
break;
|
||||
|
||||
case CAHUTE_USB_DETECTION_ENTRY_TYPE_SCSI:
|
||||
type_name = "fx-CG or compatible";
|
||||
break;
|
||||
|
||||
default:
|
||||
type_name = "(unknown)";
|
||||
}
|
||||
|
||||
printf("New entry data:\n");
|
||||
printf(
|
||||
"- Address: %03d:%03d\n",
|
||||
entry->cahute_usb_detection_entry_bus,
|
||||
entry->cahute_usb_detection_entry_address
|
||||
);
|
||||
printf("- Type: %s\n", type_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int err;
|
||||
|
||||
err = cahute_detect_usb(&my_callback, NULL);
|
||||
if (err)
|
||||
fprintf(stderr, "Cahute has returned error 0x%04X.\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
.. _guide-developer-detect-usb:
|
||||
|
||||
As a developer, I want to list calculators connected by USB
|
||||
===========================================================
|
||||
|
||||
In order to list calculators connected by USB, you must use
|
||||
:c:func:`cahute_detect_usb`, while providing it with a callback to either
|
||||
add the USB device to your list or display it.
|
||||
|
||||
An example program using this function is the following:
|
||||
|
||||
.. literalinclude:: detect-usb.c
|
||||
:language: c
|
||||
|
||||
An example output for this program is the following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
New entry data:
|
||||
- Address: 003:042
|
||||
- Type: fx-9860G or compatible
|
||||
New entry data:
|
||||
- Address: 003:043
|
||||
- Type: fx-CG or compatible
|
||||
|
||||
.. note::
|
||||
|
||||
On Linux, you can compare this output to the output of ``lsusb``, for
|
||||
example in the case above:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ lsusb
|
||||
...
|
||||
Bus 003 Device 042: ID 07cf:6101 Casio Computer Co., Ltd fx-9750gII
|
||||
Bus 003 Device 043: ID 07cf:6102 Casio Computer Co., Ltd fx-CP400
|
||||
...
|
|
@ -0,0 +1,58 @@
|
|||
/* Compile using: gcc open-usb-link.c `pkg-config cahute --cflags --libs`. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cahute.h>
|
||||
|
||||
struct my_detection_cookie {
|
||||
int found_bus;
|
||||
int found_address;
|
||||
};
|
||||
|
||||
int my_detection_callback(
|
||||
struct my_detection_cookie *cookie,
|
||||
cahute_usb_detection_entry const *entry
|
||||
) {
|
||||
/* We only want fx-9860G and compatible. */
|
||||
if (entry->cahute_usb_detection_entry_type
|
||||
!= CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN)
|
||||
return 0; /* Continue. */
|
||||
|
||||
cookie->found_bus = entry->cahute_usb_detection_entry_bus;
|
||||
cookie->found_address = entry->cahute_usb_detection_entry_address;
|
||||
return 1; /* Interrupt and return CAHUTE_ERROR_INT. */
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct my_detection_cookie cookie;
|
||||
cahute_link *link;
|
||||
int err;
|
||||
|
||||
/* This either returns 0 if detection has gotten to the end without finding
|
||||
* a suitable device, CAHUTE_ERROR_INT if a suitable device has been
|
||||
* found (due to our callback having returned 1), or another error. */
|
||||
err = cahute_detect_usb(
|
||||
(cahute_detect_usb_entry_func *)&my_detection_callback,
|
||||
&cookie
|
||||
);
|
||||
if (!err) {
|
||||
fprintf(stderr, "No USB calculator detected.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (err != CAHUTE_ERROR_INT) {
|
||||
fprintf(stderr, "cahute_detect_usb has returned error 0x%04X.\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
err =
|
||||
cahute_open_usb_link(&link, 0, cookie.found_bus, cookie.found_address);
|
||||
if (err) {
|
||||
fprintf(stderr, "cahute_open_usb has returned error 0x%04X.\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Link successfully opened!\n");
|
||||
|
||||
cahute_close_link(link);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
As a developer, I want to open a link to a calculator connected by USB
|
||||
======================================================================
|
||||
|
||||
In order to open the link to the calculator, the steps are the following:
|
||||
|
||||
1. Either request USB device address from the user, or use USB device
|
||||
detection to find out the first available device; see
|
||||
:ref:`guide-developer-detect-usb` for more information.
|
||||
2. Call :c:func:`cahute_open_usb_link` with the device address.
|
||||
3. *Profit!*
|
||||
4. Call :c:func:`cahute_close_link` to close the link.
|
||||
|
||||
An example program to do this is the following:
|
||||
|
||||
.. literalinclude:: open-usb-link.c
|
||||
:language: c
|
|
@ -0,0 +1,135 @@
|
|||
.. _guide-install:
|
||||
|
||||
Installing Cahute
|
||||
=================
|
||||
|
||||
In order to install Cahute's library and command-line utilities, the
|
||||
instructions depends on the system you want to install it on.
|
||||
|
||||
.. note::
|
||||
|
||||
The guides expect ``p7`` and ``p7screen`` to be directly usable in your
|
||||
command-line shell at the end of the installation process, i.e. that:
|
||||
|
||||
* Either both executables are placed in a directory already referenced
|
||||
by your ``$PATH``;
|
||||
* Or the directory in which both executables are placed is added to
|
||||
your ``$PATH``, and your shell has been updated to take the change
|
||||
into account.
|
||||
|
||||
If neither of these is the case for your system, you will need to
|
||||
tweak the commands to point to the right executable in an absolute or
|
||||
relative fashion, e.g. ``/opt/cahute/bin/p7 info``.
|
||||
|
||||
|archlinux| Archlinux, |manjaro| Manjaro Linux
|
||||
----------------------------------------------
|
||||
|
||||
Cahute and its command-line utilities are present on the
|
||||
`Archlinux User Repository`_, you can pop up your favourite pacman frontend
|
||||
and install the `cahute <cahute on AUR_>`_ package:
|
||||
|
||||
* Using paru_::
|
||||
|
||||
paru -S cahute
|
||||
|
||||
* Using pikaur_::
|
||||
|
||||
pikaur -S cahute
|
||||
|
||||
Once installed, it is recommended to add your user to the ``uucp`` group,
|
||||
for access to serial and USB devices, by running the following command
|
||||
**as root** then restarting your session::
|
||||
|
||||
usermod -a -G uucp <your-username>
|
||||
|
||||
.. _build-cahute:
|
||||
|
||||
|linux| Other Linux distributions
|
||||
---------------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
This guide may not be exhaustive, and a package may exist for your
|
||||
distribution. Please check with your distribution's package registry
|
||||
and/or wiki before proceeding!
|
||||
|
||||
If no package exists for your distribution, or you are to package Cahute for
|
||||
your distribution, you can build the command-line utilities yourself.
|
||||
|
||||
First, you need to install the build and runtime dependencies for Cahute:
|
||||
|
||||
* cmake_ >= 3.16;
|
||||
* `GNU Make`_, `pkg-config`_, and other C compilation and linking utilities;
|
||||
* SDL_ >= 2.0 (for ``p7screen``);
|
||||
* libusb_.
|
||||
|
||||
For getting the source, you have the following options:
|
||||
|
||||
* You can download the latest source package at
|
||||
https://ftp.cahuteproject.org/releases\ :
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
curl -o cahute-|version|.tar.gz https\://ftp.cahuteproject.org/releases/cahute-|version|.tar.gz
|
||||
tar xvaf cahute-|version|.tar.gz
|
||||
|
||||
* You can clone the repository and checkout the tag corresponding to the
|
||||
release:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
git clone https\://gitlab.com/cahuteproject/cahute.git cahute-|version|
|
||||
(cd cahute-|version| && git checkout -f |version|)
|
||||
|
||||
The project is present in the "cahute-|version|" directory.
|
||||
In the parent directory, we are to create the ``build`` directory aside
|
||||
it, and install from it, by running the following commands:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
cmake -B build -S cahute-|version| -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake --build build
|
||||
sudo cmake --install build
|
||||
|
||||
.. warning::
|
||||
|
||||
For communicating with calculators over USB and serial, Cahute library
|
||||
and command-line utilities require access to such devices.
|
||||
|
||||
For serial devices, this is traditionally represented by being a member
|
||||
of the ``uucp`` group, defined as the group owner on ``/dev/ttyS*``
|
||||
devices; you can check this by running ``ls -l /dev/ttyS*``.
|
||||
However, by default, USB devices don't have such rules.
|
||||
|
||||
CMake automatically installs the udev rules, which means you need to
|
||||
do the following:
|
||||
|
||||
* Reload the udev daemon reload to apply the newly installed rules
|
||||
on the running system without a reboot, with this command **as root**::
|
||||
|
||||
udevadm control --reload
|
||||
|
||||
* Adding your user to the ``uucp`` group, then restarting your session::
|
||||
|
||||
usermod -a -G uucp <your-username>
|
||||
|
||||
That's it! You should be able to run the following command::
|
||||
|
||||
p7 --version
|
||||
|
||||
.. _Archlinux User Repository: https://aur.archlinux.org/
|
||||
.. _cahute on AUR: https://aur.archlinux.org/packages/cahute
|
||||
.. _p7 on AUR: https://aur.archlinux.org/packages/p7
|
||||
.. _p7screen on AUR: https://aur.archlinux.org/packages/p7screen
|
||||
.. _paru: https://github.com/morganamilo/paru
|
||||
.. _pikaur: https://github.com/actionless/pikaur
|
||||
|
||||
.. _cmake: https://cmake.org/
|
||||
.. _GNU Make: https://www.gnu.org/software/make/
|
||||
.. _pkg-config: https://git.sr.ht/~kaniini/pkgconf
|
||||
.. _SDL: https://www.libsdl.org/
|
||||
.. _libusb: https://libusb.info/
|
||||
|
||||
.. |archlinux| image:: arch.svg
|
||||
.. |manjaro| image:: manjaro.svg
|
||||
.. |linux| image:: linux.svg
|
|
@ -0,0 +1,348 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="256" height="256" version="1.1" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Tux</title>
|
||||
<defs id="tux_fx">
|
||||
<linearGradient id="gradient_belly_shadow">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity=".25" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="gradient_wing_tip_right_shadow">
|
||||
<stop stop-color="#110800" offset="0"/>
|
||||
<stop stop-color="#a65a00" stop-opacity=".8" offset=".59"/>
|
||||
<stop stop-color="#ff921e" stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="gradient_eyeball">
|
||||
<stop stop-color="#fefefc" offset="0"/>
|
||||
<stop stop-color="#fefefc" offset=".75"/>
|
||||
<stop stop-color="#d4d4d4" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="gradient_eyebrow">
|
||||
<stop stop-color="#646464" stop-opacity="0" offset="0"/>
|
||||
<stop stop-color="#646464" stop-opacity=".58" offset=".31"/>
|
||||
<stop stop-color="#646464" offset=".47"/>
|
||||
<stop stop-color="#646464" stop-opacity=".26" offset=".73"/>
|
||||
<stop stop-color="#646464" stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="gradient_nares">
|
||||
<stop stop-color="#3a2903" offset="0"/>
|
||||
<stop stop-color="#735208" offset=".55"/>
|
||||
<stop stop-color="#ac8c04" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="fill_belly_shadow_left" cx="0" cy="0" r="1" gradientTransform="matrix(19,0,0,18,61.18,121.19)" gradientUnits="userSpaceOnUse" href="#gradient_belly_shadow" xlink:href="#gradient_belly_shadow"/>
|
||||
<radialGradient id="fill_belly_shadow_right" cx="0" cy="0" r="1" gradientTransform="matrix(23.6,0,0,18,125.74,131.6)" gradientUnits="userSpaceOnUse" href="#gradient_belly_shadow" xlink:href="#gradient_belly_shadow"/>
|
||||
<radialGradient id="fill_belly_shadow_middle" cx="0" cy="0" r="1" gradientTransform="matrix(9.35,0,0,10,94.21,127.47)" gradientUnits="userSpaceOnUse" href="#gradient_belly_shadow" xlink:href="#gradient_belly_shadow"/>
|
||||
<linearGradient id="fill_foot_left_base" x1="23.18" x2="64.31" y1="193.01" y2="262.02" gradientUnits="userSpaceOnUse" href="#gradient_foot_left_layer_1">
|
||||
<stop stop-color="#b98309" offset="0"/>
|
||||
<stop stop-color="#382605" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_foot_left_glare" x1="64.47" x2="77.41" y1="210.83" y2="235.21" gradientUnits="userSpaceOnUse" href="#gradient_foot_left_glare">
|
||||
<stop stop-color="#ebc40c" offset="0"/>
|
||||
<stop stop-color="#ebc40c" stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_foot_right_shadow" x1="146.93" x2="150.2" y1="211.96" y2="235.73" gradientUnits="userSpaceOnUse" href="#gradient_foot_right_shadow">
|
||||
<stop offset="0"/>
|
||||
<stop stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_foot_right_base" x1="151.5" x2="192.94" y1="253.02" y2="185.84" gradientUnits="userSpaceOnUse" href="#gradient_foot_right_layer_1">
|
||||
<stop stop-color="#3e2a06" offset="0"/>
|
||||
<stop stop-color="#ad780a" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_foot_right_glare" x1="162.81" x2="161.59" y1="180.67" y2="191.64" gradientUnits="userSpaceOnUse" href="#gradient_foot_right_glare">
|
||||
<stop stop-color="#f3cd0c" offset="0"/>
|
||||
<stop stop-color="#f3cd0c" stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="fill_wing_tip_right_shadow_lower" cx="0" cy="0" r="1" gradientTransform="matrix(18.99 5.0884 -5.342 19.937 169.71 194.53)" gradientUnits="userSpaceOnUse" href="#gradient_wing_tip_right_shadow" xlink:href="#gradient_wing_tip_right_shadow"/>
|
||||
<radialGradient id="fill_wing_tip_right_shadow_upper" cx="0" cy="0" r="1" gradientTransform="matrix(19.722 -.83351 .62745 14.847 169.71 189.89)" gradientUnits="userSpaceOnUse" href="#gradient_wing_tip_right_shadow" xlink:href="#gradient_wing_tip_right_shadow"/>
|
||||
<radialGradient id="fill_wing_tip_right_glare_1" cx="0" cy="0" r="1" gradientTransform="matrix(6.3736 2.7713 -1.28 2.9438 184.65 176.62)" gradientUnits="userSpaceOnUse" href="#gradient_wing_tip_right_glare_1">
|
||||
<stop stop-color="#7c7c7c" offset="0"/>
|
||||
<stop stop-color="#7c7c7c" stop-opacity=".33" offset="1"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="fill_wing_tip_right_glare_2" x1="165.69" x2="168.27" y1="173.58" y2="173.47" gradientUnits="userSpaceOnUse" href="#gradient_wing_tip_right_glare_2">
|
||||
<stop stop-color="#7c7c7c" offset="0"/>
|
||||
<stop stop-color="#7c7c7c" stop-opacity=".33" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="fill_eyeball_left" cx="0" cy="0" r="1" gradientTransform="matrix(10.239 -.10723 .1642 15.679 86.49 51.41)" gradientUnits="userSpaceOnUse" href="#gradient_eyeball" xlink:href="#gradient_eyeball"/>
|
||||
<linearGradient id="fill_pupil_left_glare" x1="84.29" x2="89.32" y1="46.64" y2="55.63" gradientUnits="userSpaceOnUse" href="#gradient_pupil_left_glare">
|
||||
<stop stop-color="#757574" stop-opacity="0" offset="0"/>
|
||||
<stop stop-color="#757574" offset=".25"/>
|
||||
<stop stop-color="#757574" offset=".5"/>
|
||||
<stop stop-color="#757574" stop-opacity="0" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="fill_eyelid_left" cx="0" cy="0" r="1" gradientTransform="matrix(6.167 -1.0154 .93742 5.6933 84.89 43.74)" gradientUnits="userSpaceOnUse" href="#gradient_eyelid_left">
|
||||
<stop stop-color="#c8c8c8" offset="0"/>
|
||||
<stop stop-color="#797978" offset="1"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="fill_eyebrow_left" x1="83.59" x2="94.48" y1="32.51" y2="43.63" gradientUnits="userSpaceOnUse" href="#gradient_eyebrow" xlink:href="#gradient_eyebrow"/>
|
||||
<radialGradient id="fill_eyeball_right" cx="0" cy="0" r="1" gradientTransform="matrix(13.633 -.42844 .49252 15.672 118.06 51.41)" gradientUnits="userSpaceOnUse" href="#gradient_eyeball" xlink:href="#gradient_eyeball"/>
|
||||
<linearGradient id="fill_pupil_right_glare" x1="117.87" x2="123.66" y1="47.25" y2="54.11" gradientUnits="userSpaceOnUse" href="#gradient_pupil_right_glare_2">
|
||||
<stop stop-color="#949494" stop-opacity=".39" offset="0"/>
|
||||
<stop stop-color="#949494" offset=".5"/>
|
||||
<stop stop-color="#949494" stop-opacity=".39" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_eyelid_right" x1="112.9" x2="131.32" y1="36.23" y2="47.01" gradientUnits="userSpaceOnUse" href="#gradient_eyelid_right">
|
||||
<stop stop-color="#747474" offset="0"/>
|
||||
<stop stop-color="#8c8c8c" offset=".13"/>
|
||||
<stop stop-color="#a4a4a4" offset=".25"/>
|
||||
<stop stop-color="#d4d4d4" offset=".5"/>
|
||||
<stop stop-color="#d4d4d4" offset=".62"/>
|
||||
<stop stop-color="#7c7c7c" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="fill_eyebrow_right" x1="119.16" x2="131.42" y1="31.56" y2="43.14" gradientUnits="userSpaceOnUse" href="#gradient_eyebrow" xlink:href="#gradient_eyebrow"/>
|
||||
<radialGradient id="fill_beak_base" cx="0" cy="0" r="1" gradientTransform="matrix(9.2552 -6.7243 6.1012 8.3976 97.64 60.12)" gradientUnits="userSpaceOnUse" href="#gradient_beak_base">
|
||||
<stop stop-color="#020204" offset="0"/>
|
||||
<stop stop-color="#020204" offset=".73"/>
|
||||
<stop stop-color="#5c5c5c" offset="1"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="fill_mandible_lower_base" cx="0" cy="0" r="1" gradientTransform="matrix(25.101 -10.346 7.267 17.631 109.77 70.61)" gradientUnits="userSpaceOnUse" href="#gradient_mandible_lower">
|
||||
<stop stop-color="#d2940a" offset="0"/>
|
||||
<stop stop-color="#d89c08" offset=".75"/>
|
||||
<stop stop-color="#b67e07" offset=".87"/>
|
||||
<stop stop-color="#946106" offset="1"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="fill_mandible_upper_base" x1="78.09" x2="126.77" y1="69.26" y2="68.88" gradientUnits="userSpaceOnUse" href="#gradient_mandible_upper">
|
||||
<stop stop-color="#ad780a" offset="0"/>
|
||||
<stop stop-color="#d89e08" offset=".12"/>
|
||||
<stop stop-color="#edb80b" offset=".25"/>
|
||||
<stop stop-color="#ebc80d" offset=".39"/>
|
||||
<stop stop-color="#f5d838" offset=".53"/>
|
||||
<stop stop-color="#f6d811" offset=".77"/>
|
||||
<stop stop-color="#f5cd31" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="fill_naris_left" cx="0" cy="0" r="1" gradientTransform="matrix(1.32,0,0,1.42,92.11,59.88)" gradientUnits="userSpaceOnUse" href="#gradient_nares" xlink:href="#gradient_nares"/>
|
||||
<radialGradient id="fill_naris_right" cx="0" cy="0" r="1" gradientTransform="matrix(2.78,0,0,1.62,104.65,59.7)" gradientUnits="userSpaceOnUse" href="#gradient_nares" xlink:href="#gradient_nares"/>
|
||||
<linearGradient id="fill_beak_corner" x1="126.74" x2="126.74" y1="67.49" y2="71.09" gradientUnits="userSpaceOnUse" href="#gradient_beak_corner">
|
||||
<stop stop-color="#f5ce2d" offset="0"/>
|
||||
<stop stop-color="#d79b08" offset="1"/>
|
||||
</linearGradient>
|
||||
<filter id="blur_belly_shadow_left" x="-.049919" y="-.045849" width="1.0998" height="1.0917">
|
||||
<feGaussianBlur stdDeviation="0.64 0.55"/>
|
||||
</filter>
|
||||
<filter id="blur_belly_shadow_right" x="-.050747" y="-.073203" width="1.1015" height="1.1464">
|
||||
<feGaussianBlur stdDeviation="0.98"/>
|
||||
</filter>
|
||||
<filter id="blur_belly_shadow_middle" x="-.087319" y="-.081682" width="1.1746" height="1.1634">
|
||||
<feGaussianBlur stdDeviation="0.68"/>
|
||||
</filter>
|
||||
<filter id="blur_belly_shadow_lower" x="-.81954" y="-.057993" width="2.6391" height="1.116">
|
||||
<feGaussianBlur stdDeviation="1.25"/>
|
||||
</filter>
|
||||
<filter id="blur_belly_glare" x="-.49197" y="-.59291" width="1.9839" height="2.1858">
|
||||
<feGaussianBlur stdDeviation="1.78 2.19"/>
|
||||
</filter>
|
||||
<filter id="blur_head_glare" x="-.29258" y="-.30859" width="1.5852" height="1.6172">
|
||||
<feGaussianBlur stdDeviation="1.73"/>
|
||||
</filter>
|
||||
<filter id="blur_neck_glare" x="-.17841" y="-.16017" width="1.3568" height="1.3203">
|
||||
<feGaussianBlur stdDeviation="0.78"/>
|
||||
</filter>
|
||||
<filter id="blur_wing_left_glare" x="-.10145" y="-.042862" width="1.2029" height="1.0857">
|
||||
<feGaussianBlur stdDeviation="0.98"/>
|
||||
</filter>
|
||||
<filter id="blur_wing_right_glare" x="-.1179" y="-.040212" width="1.2358" height="1.0804">
|
||||
<feGaussianBlur stdDeviation="1.19 1.17"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_left_layer_1" x="-.10746" y="-.10845" width="1.2149" height="1.2169">
|
||||
<feGaussianBlur stdDeviation="3.38"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_left_layer_2" x="-.075378" y="-.069657" width="1.1508" height="1.1393">
|
||||
<feGaussianBlur stdDeviation="2.1 2.06"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_left_glare" x="-.033862" y="-.018668" width="1.0677" height="1.0373">
|
||||
<feGaussianBlur stdDeviation="0.32"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_right_shadow" x="-.076044" y="-.068073" width="1.1521" height="1.1361">
|
||||
<feGaussianBlur stdDeviation="1.95 1.9"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_right_layer_1" x="-.14509" y="-.14307" width="1.2902" height="1.2861">
|
||||
<feGaussianBlur stdDeviation="4.12"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_right_layer_2" x="-.11511" y="-.12498" width="1.2302" height="1.25">
|
||||
<feGaussianBlur stdDeviation="3.12 3.37"/>
|
||||
</filter>
|
||||
<filter id="blur_foot_right_glare" x="-.020751" y="-.12827" width="1.0415" height="1.2565">
|
||||
<feGaussianBlur stdDeviation="0.41"/>
|
||||
</filter>
|
||||
<filter id="blur_wing_tip_right_shadow_lower" x="-.20044" y="-.23395" width="1.4009" height="1.4679">
|
||||
<feGaussianBlur stdDeviation="2.45"/>
|
||||
</filter>
|
||||
<filter id="blur_wing_tip_right_shadow_upper" x="-.091629" y="-.10698" width="1.1833" height="1.214">
|
||||
<feGaussianBlur stdDeviation="1.12 0.81"/>
|
||||
</filter>
|
||||
<filter id="blur_wing_tip_right_glare" x="-.070171" y="-.14998" width="1.1403" height="1.3">
|
||||
<feGaussianBlur stdDeviation="0.88"/>
|
||||
</filter>
|
||||
<filter id="blur_pupil_left_glare" x="-.23333" y="-.14544" width="1.4667" height="1.2909">
|
||||
<feGaussianBlur stdDeviation="0.44"/>
|
||||
</filter>
|
||||
<filter id="blur_eyebrow_left" x="-.023848" y="-.026523" width="1.0477" height="1.053">
|
||||
<feGaussianBlur stdDeviation="0.12"/>
|
||||
</filter>
|
||||
<filter id="blur_pupil_right_glare" x="-.17959" y="-.18232" width="1.3592" height="1.3646">
|
||||
<feGaussianBlur stdDeviation="0.45"/>
|
||||
</filter>
|
||||
<filter id="blur_eyebrow_right" x="-.023601" y="-.025574" width="1.0472" height="1.0511">
|
||||
<feGaussianBlur stdDeviation="0.13"/>
|
||||
</filter>
|
||||
<filter id="blur_beak_shadow_lower" x="-.076202" y="-.12888" width="1.1524" height="1.2578">
|
||||
<feGaussianBlur stdDeviation="1.75"/>
|
||||
</filter>
|
||||
<filter id="blur_beak_shadow_upper" x="-.036392" y="-.074089" width="1.0728" height="1.1482">
|
||||
<feGaussianBlur stdDeviation="0.8 0.74"/>
|
||||
</filter>
|
||||
<filter id="blur_mandible_lower_glare" x="-.15437" y="-.21067" width="1.3087" height="1.4213">
|
||||
<feGaussianBlur stdDeviation="0.77"/>
|
||||
</filter>
|
||||
<filter id="blur_mandible_upper_shadow" x="-.034221" y="-.078979" width="1.0684" height="1.158">
|
||||
<feGaussianBlur stdDeviation="0.65"/>
|
||||
</filter>
|
||||
<filter id="blur_mandible_upper_glare" x="-.16065" y="-.13004" width="1.3213" height="1.2601">
|
||||
<feGaussianBlur stdDeviation="0.73"/>
|
||||
</filter>
|
||||
<filter id="blur_naris_left" x="-.12244" y="-.11124" width="1.2449" height="1.2225">
|
||||
<feGaussianBlur stdDeviation="0.1"/>
|
||||
</filter>
|
||||
<filter id="blur_naris_right" x="-.049122" y="-.093498" width="1.0982" height="1.187">
|
||||
<feGaussianBlur stdDeviation="0.1"/>
|
||||
</filter>
|
||||
<filter id="blur_beak_corner" x="-.11091" y="-.09064" width="1.2218" height="1.1813">
|
||||
<feGaussianBlur stdDeviation="0.23"/>
|
||||
</filter>
|
||||
<clipPath id="clip_body">
|
||||
<use href="#body_base" xlink:href="#body_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_wing_left">
|
||||
<use href="#wing_left_base" xlink:href="#wing_left_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_wing_right">
|
||||
<use href="#wing_right_base" xlink:href="#wing_right_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_foot_left">
|
||||
<use href="#foot_left_base" xlink:href="#foot_left_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_foot_right">
|
||||
<use href="#foot_right_base" xlink:href="#foot_right_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_wing_tip_right">
|
||||
<use href="#wing_tip_right_base" xlink:href="#wing_tip_right_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_eye_left">
|
||||
<use href="#eyeball_left" xlink:href="#eyeball_left"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_pupil_left">
|
||||
<use href="#pupil_left_base" xlink:href="#pupil_left_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_eye_right">
|
||||
<use href="#eyeball_right" xlink:href="#eyeball_right"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_pupil_right">
|
||||
<use href="#pupil_right_base" xlink:href="#pupil_right_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_mandible_lower">
|
||||
<use href="#mandible_lower_base" xlink:href="#mandible_lower_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_mandible_upper">
|
||||
<use href="#mandible_upper_base" xlink:href="#mandible_upper_base"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip_beak">
|
||||
<use href="#mandible_lower_base" xlink:href="#mandible_lower_base"/>
|
||||
<use href="#mandible_upper_base" xlink:href="#mandible_upper_base"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="tux" transform="translate(20)">
|
||||
<g id="body">
|
||||
<path id="body_base" d="m106.95 0c-6 0-12.02 1.18-17.46 4.12-5.78 3.11-10.52 8.09-13.43 13.97-2.92 5.88-4.06 12.16-4.24 19.08-0.33 13.14 0.3 26.92 1.29 39.41 0.26 3.8 0.74 6.02 0.25 9.93-1.62 8.3-8.88 13.88-12.76 21.17-4.27 8.04-6.07 17.13-9.29 25.65-2.95 7.79-7.09 15.1-9.88 22.95-3.91 10.97-5.08 23.03-2.5 34.39 1.97 8.66 6.08 16.78 11.62 23.73-0.8 1.44-1.58 2.91-2.4 4.34-2.57 4.43-5.71 8.64-7.17 13.55-0.73 2.45-1.02 5.07-0.55 7.59s1.75 4.93 3.75 6.53c1.31 1.04 2.9 1.72 4.53 2.1 1.63 0.37 3.32 0.46 5 0.43 6.37-0.14 12.55-2.07 18.71-3.69 3.66-0.96 7.34-1.81 11.03-2.58 13.14-2.69 27.8-1.61 39.99 0.15 4.13 0.63 8.23 1.44 12.29 2.43 6.36 1.54 12.69 3.5 19.23 3.69 1.72 0.05 3.46-0.03 5.14-0.4 1.68-0.38 3.31-1.06 4.65-2.13 2.01-1.6 3.29-4.02 3.76-6.54s0.18-5.15-0.56-7.61c-1.48-4.92-4.65-9.11-7.27-13.52-1.04-1.75-2-3.53-3.03-5.28 7.9-8.87 14.26-19.13 17.94-30.4 4.01-12.3 4.75-25.55 3.06-38.38s-5.76-25.27-11.11-37.05c-6.72-14.76-12.37-20.1-16.47-33.07-4.42-14.02-0.77-30.61-4.06-43.32-1.17-4.32-3.04-8.45-5.45-12.23-2.82-4.43-6.4-8.39-10.65-11.47-6.78-4.92-15.3-7.54-23.96-7.54z" fill="#020204"/>
|
||||
<path id="belly" d="m83.13 74c-0.9 1.13-1.48 2.49-1.84 3.89-0.35 1.4-0.48 2.85-0.54 4.3-0.11 2.89 0.07 5.83-0.7 8.62-0.82 2.98-2.65 5.57-4.44 8.08-3.11 4.36-6.25 8.84-7.78 13.97-0.93 3.1-1.24 6.39-0.91 9.62-3.47 5.1-6.48 10.53-8.98 16.18-3.78 8.57-6.37 17.69-7.28 27.01-1.12 11.41 0.34 23.15 4.85 33.69 3.25 7.63 8.11 14.6 14.38 20.04 3.18 2.76 6.72 5.11 10.5 6.97 13.11 6.45 29.31 6.46 42.2-0.41 6.74-3.59 12.43-8.84 17.91-14.15 3.3-3.2 6.59-6.48 9.11-10.32 4.85-7.41 6.54-16.41 7.59-25.2 1.83-15.36 1.89-31.6-4.85-45.53-2.32-4.8-5.41-9.22-9.12-13.05-0.98-6.7-2.93-13.27-5.76-19.42-2.05-4.45-4.54-8.68-6.44-13.18-0.78-1.85-1.46-3.75-2.32-5.56-0.87-1.81-1.93-3.55-3.39-4.94-1.48-1.42-3.33-2.43-5.28-3.07-1.95-0.65-4.01-0.94-6.06-1.04-4.11-0.21-8.22 0.33-12.33 0.16-3.27-0.13-6.53-0.7-9.8-0.51-1.63 0.1-3.26 0.39-4.78 1.01-1.52 0.61-2.92 1.56-3.94 2.84z" fill="#fdfdfb"/>
|
||||
<g id="body_self_shadows">
|
||||
<path id="belly_shadow_left" d="m68.67 115.18c0.87 1.31-0.55 5.84 19.86 2.94 0 0-3.59 0.39-7.12 1.21-5.49 1.84-10.27 3.89-13.97 6.61-3.65 2.7-6.33 6.21-9.68 9.22 0 0 5.43-9.92 6.78-12.91 1.36-2.99-0.22-2.85 0.85-7.25s3.69-8.63 3.69-8.63-2.14 6.22-0.41 8.81z" clip-path="url(#clip_body)" fill="url(#fill_belly_shadow_left)" filter="url(#blur_belly_shadow_left)" opacity=".25"/>
|
||||
<path id="belly_shadow_right" d="m134.28 113.99c-4.16 2.9-6.6 2.56-11.64 3.12-5.05 0.57-18.7 0.36-18.7 0.36s1.97-0.03 6.36 0.78c4.38 0.82 13.31 1.6 18.34 3.51 5.04 1.92 6.87 2.47 9.93 4.4 4.35 2.75 7.55 7.06 11.71 10.08 0 0 0.2-4-1.48-6.99s-6.2-7.7-7.53-12.1c-1.32-4.4-1.96-13.04-1.96-13.04s-0.88 6.99-5.03 9.88z" clip-path="url(#clip_body)" fill="url(#fill_belly_shadow_right)" filter="url(#blur_belly_shadow_right)" opacity=".42"/>
|
||||
<path id="belly_shadow_middle" d="m95.17 107.81c-0.16 1.25-0.36 2.5-0.6 3.74-0.12 0.61-0.26 1.22-0.48 1.8-0.23 0.58-0.56 1.14-1.02 1.55-0.41 0.37-0.9 0.62-1.4 0.85-1.94 0.88-4.01 1.47-6.12 1.74 0.84 0.06 1.68 0.14 2.53 0.23 0.53 0.06 1.06 0.12 1.57 0.25 0.52 0.14 1.03 0.34 1.46 0.65 0.47 0.35 0.84 0.82 1.12 1.34 0.55 1.02 0.73 2.2 0.83 3.37 0.13 1.48 0.14 2.98 0.03 4.46 0.1-0.99 0.31-1.98 0.62-2.92 0.57-1.72 1.47-3.32 2.69-4.65 0.49-0.52 1.02-1.01 1.6-1.42 1.79-1.26 4.07-1.81 6.24-1.51-2.21 0.09-4.44-0.6-6.2-1.93-0.9-0.68-1.68-1.52-2.22-2.5-0.84-1.52-1.08-3.37-0.65-5.05z" clip-path="url(#clip_body)" fill="url(#fill_belly_shadow_middle)" filter="url(#blur_belly_shadow_middle)" opacity=".2"/>
|
||||
<path id="belly_shadow_lower" d="m89.85 137.14c-1.06 4.03-1.79 8.15-2.17 12.31-0.55 5.87-0.42 11.78-0.74 17.67-0.26 4.99-0.85 10.04 0.02 14.97 0.41 2.35 1.15 4.64 2.2 6.78 0.16-0.82 0.29-1.64 0.36-2.47 0.37-4-0.3-8.01-0.53-12.01-0.4-7.02 0.57-14.04 0.97-21.06 0.3-5.39 0.27-10.8-0.11-16.19z" clip-path="url(#clip_body)" filter="url(#blur_belly_shadow_lower)" opacity=".11"/>
|
||||
</g>
|
||||
<g id="body_glare">
|
||||
<path id="belly_glare" d="m160.08 131.23c1.03-0.16 7.34 5.21 6.48 7.21-0.86 1.99-2.49 0.79-3.65 0.8-1.16 0.02-4.33 1.46-4.86 0.55-0.54-0.91 1.4-3.03 2.41-4.81 0.82-1.43-1.4-3.59-0.38-3.75z" clip-path="url(#clip_body)" fill="#7c7c7c" filter="url(#blur_belly_glare)" opacity=".75"/>
|
||||
<path id="head_glare" d="m121.52 11.12c-2.21 1.56-1.25 3.51-0.3 5.46 0.95 1.96-2.09 7.59-2.12 7.83s5.98-2.85 7.62-4.87c1.94-2.37 6.83 3.22 6.56 2.37 0.01-1.52-9.55-12.34-11.76-10.79z" clip-path="url(#clip_body)" fill="#7c7c7c" filter="url(#blur_head_glare)"/>
|
||||
<path id="neck_glare" d="m138.27 76.63c-1.86 1.7 0.88 4.25 2.17 7.24 0.81 1.86 3.04 4.49 5.2 4.07 1.63-0.32 2.63-2.66 2.48-4.3-0.3-3.18-2.98-3.93-4.93-5.02-1.54-0.86-3.61-3.18-4.92-1.99z" clip-path="url(#clip_body)" fill="#838384" filter="url(#blur_neck_glare)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="wings">
|
||||
<g id="wing_left">
|
||||
<path id="wing_left_base" d="m63.98 100.91c-6.1 6.92-12.37 13.63-15.81 21.12-1.71 3.8-2.51 7.93-3.68 11.93-1.32 4.54-3.12 8.94-5.14 13.22-1.87 3.95-3.93 7.81-5.98 11.66-1.5 2.81-3.02 5.67-3.54 8.81-0.41 2.48-0.18 5.04 0.46 7.47 0.63 2.43 1.64 4.75 2.79 6.98 4.88 9.55 12.21 17.77 20.89 24.07 3.94 2.85 8.15 5.32 12.58 7.35 2.4 1.09 4.92 2.07 7.56 2.11 1.32 0.03 2.65-0.19 3.86-0.72 1.2-0.53 2.28-1.38 3-2.49 0.88-1.36 1.18-3.05 1-4.66s-0.81-3.15-1.65-4.53c-2.06-3.38-5.31-5.83-8.44-8.25-6.76-5.23-13.29-10.76-19.55-16.58-1.76-1.65-3.53-3.34-4.76-5.42-1.2-2.02-1.85-4.32-2.29-6.63-1.21-6.33-0.9-12.99 1.25-19.07 0.85-2.38 1.96-4.65 3.04-6.93 1.86-3.95 3.62-7.98 6.07-11.6 3.05-4.51 7.13-8.33 9.61-13.17 2.1-4.09 2.95-8.68 3.76-13.2 0.64-3.54 1.85-7 2.47-10.54-1.21 2.3-5.11 6.07-7.5 9.07z" fill="#020204"/>
|
||||
<path id="wing_left_glare" d="m56.96 126.1c-2 1.84-3.73 3.97-5.13 6.31-2.3 3.84-3.65 8.16-5.33 12.31-1.24 3.09-2.69 6.2-2.86 9.53-0.09 1.71 0.16 3.42 0.22 5.13s-0.1 3.49-0.94 4.98c-0.7 1.25-1.87 2.23-3.22 2.71 1.83 0.61 3.45 1.79 4.6 3.33 0.96 1.3 1.58 2.81 2.41 4.18 0.68 1.12 1.51 2.16 2.54 2.97 1.02 0.82 2.25 1.4 3.54 1.56 1.79 0.23 3.65-0.36 4.97-1.58-1.66-15.55-0.14-31.42 4.44-46.37 0.29-0.94 0.59-1.89 0.67-2.87 0.07-0.99-0.12-2.03-0.72-2.81-0.31-0.42-0.74-0.75-1.23-0.96-0.48-0.2-1.02-0.28-1.54-0.21-0.52 0.06-1.03 0.26-1.45 0.57-0.42 0.32-0.76 0.74-0.97 1.22z" clip-path="url(#clip_wing_left)" fill="#7c7c7c" filter="url(#blur_wing_left_glare)" opacity=".95"/>
|
||||
</g>
|
||||
<g id="wing_right">
|
||||
<path id="wing_right_base" d="m162.76 127.12c5.24 4.22 8.57 10.59 9.6 17.24 0.8 5.18 0.28 10.51-0.89 15.62-1.17 5.12-2.97 10.06-4.77 15-0.71 1.96-1.43 3.95-1.71 6.02-0.29 2.08-0.11 4.27 0.89 6.11 1.15 2.11 3.29 3.56 5.59 4.24 2.27 0.68 4.72 0.66 7.02 0.09s6.17-1.31 8.04-2.77c4.75-3.69 5.88-10.1 7.01-15.72 1.17-5.87 0.6-12.02-0.43-17.95-1.41-8.09-3.78-15.99-6.79-23.62-2.22-5.62-5.06-10.98-8.44-15.96-3.32-4.89-8.02-8.7-11.5-13.48-1.21-1.66-2.66-3.38-3.84-5.06-2.56-3.62-1.98-2.94-3.57-5.29-1.15-1.7-2.97-2.28-4.88-3.02-1.92-0.74-4.06-0.96-6.04-0.41-2.6 0.73-4.73 2.79-5.86 5.24-1.13 2.46-1.33 5.28-0.89 7.95 0.57 3.44 2.14 6.64 3.92 9.64 2 3.39 4.32 6.66 7.35 9.18 3.16 2.63 6.98 4.37 10.19 6.95z" fill="#020204"/>
|
||||
<path id="wing_right_glare" d="m150.42 118.99c0.42 0.4 0.86 0.81 1.31 1.19 3.22 2.63 4.93 5.58 8.2 8.16 5.34 4.22 10.75 11.5 11.8 18.15 0.82 5.19-0.26 8.01-1.58 14.12-1.32 6.12-5.06 14.78-7.09 20.68-0.8 2.35 1.64 1.38 1.32 3.86-0.16 1.22-0.18 2.45-0.03 3.67 0.02-0.23 0.03-0.48 0.06-0.71 0.39-3.38 1.42-6.63 2.55-9.82 2.17-6.13 4.66-12.15 6.38-18.45 1.72-6.29 1.53-10.82 0.63-16.23-1.13-6.81-5.09-13.09-10.69-17.24-3.97-2.93-8.64-4.81-12.86-7.38z" clip-path="url(#clip_wing_right)" fill="#838384" filter="url(#blur_wing_right_glare)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="feet">
|
||||
<g id="foot_left">
|
||||
<path id="foot_left_base" d="m34.98 175.33c1.38-0.57 2.93-0.68 4.39-0.41 1.47 0.27 2.86 0.91 4.09 1.74 2.47 1.68 4.3 4.12 6.05 6.54 4.03 5.54 7.9 11.2 11.42 17.08 2.85 4.78 5.46 9.71 8.76 14.18 2.15 2.93 4.57 5.64 6.73 8.55 2.16 2.92 4.07 6.08 5.03 9.58 1.25 4.55 0.76 9.56-1.4 13.75-1.52 2.95-3.86 5.48-6.7 7.19s-5.83 2.47-9.15 2.47c-5.27 0-10.42-2.83-15.32-4.78-9.98-3.98-20.82-5.22-31.11-8.32-3.16-0.95-6.27-2.08-9.45-2.95-1.42-0.39-2.85-0.73-4.19-1.34-1.34-0.6-2.59-1.51-3.33-2.77-0.57-0.98-0.8-2.13-0.8-3.26 0-1.14 0.28-2.26 0.67-3.32 0.77-2.13 2.02-4.06 2.86-6.17 1.37-3.44 1.62-7.23 1.43-10.93-0.18-3.69-0.78-7.36-1.03-11.05-0.12-1.65-0.16-3.32 0.16-4.95 0.31-1.62 1.01-3.21 2.2-4.35 1.1-1.06 2.55-1.69 4.05-2 1.49-0.31 3.03-0.32 4.55-0.29s3.05 0.12 4.57-0.01c1.52-0.12 3.05-0.46 4.37-1.22 1.26-0.72 2.29-1.79 3.14-2.96s1.54-2.45 2.25-3.72c0.7-1.26 1.43-2.52 2.36-3.64 0.92-1.12 2.06-2.09 3.4-2.64z" fill="url(#fill_foot_left_base)"/>
|
||||
<path d="m37.16 177.7c1.25-0.5 2.67-0.56 3.98-0.26 1.32 0.3 2.55 0.94 3.61 1.77 2.14 1.65 3.62 3.97 5.05 6.26 3.42 5.54 6.76 11.15 9.92 16.86 2.4 4.31 4.68 8.7 7.62 12.65 1.95 2.62 4.18 5.03 6.17 7.62s3.76 5.41 4.64 8.56c1.14 4.05 0.68 8.54-1.28 12.26-1.42 2.68-3.58 4.96-6.2 6.48-2.61 1.52-5.67 2.28-8.69 2.14-4.82-0.22-9.23-2.63-13.77-4.26-8.71-3.16-18.14-3.59-27.08-6.05-3.2-0.87-6.32-2.03-9.53-2.84-1.43-0.36-2.88-0.66-4.23-1.23s-2.62-1.45-3.36-2.72c-0.54-0.95-0.76-2.06-0.73-3.15 0.04-1.09 0.31-2.17 0.7-3.19 0.78-2.04 2-3.88 2.78-5.92 1.19-3.08 1.34-6.47 1.12-9.76s-0.8-6.56-1-9.85c-0.08-1.48-0.1-2.97 0.2-4.41 0.3-1.45 0.93-2.85 1.98-3.89 1.14-1.13 2.7-1.74 4.29-1.99 1.58-0.24 3.19-0.13 4.78 0.01 1.6 0.14 3.2 0.32 4.8 0.23 1.6-0.1 3.22-0.49 4.54-1.39 1.2-0.81 2.1-2 2.79-3.27s1.18-2.64 1.71-3.98c0.52-1.35 1.09-2.69 1.91-3.89 0.82-1.19 1.93-2.24 3.28-2.79z" clip-path="url(#clip_foot_left)" fill="#d99a03" filter="url(#blur_foot_left_layer_1)"/>
|
||||
<path d="m35.99 174.57c1.22-0.6 2.65-0.72 3.98-0.45s2.57 0.92 3.62 1.77c2.09 1.7 3.43 4.13 4.67 6.51 2.84 5.46 5.5 11.04 8.9 16.19 2.48 3.73 5.33 7.2 7.83 10.92 3.39 5.03 6.15 10.57 7.29 16.5 0.76 4 0.74 8.31-1.18 11.9-1.27 2.37-3.32 4.31-5.75 5.52-2.42 1.22-5.21 1.71-7.92 1.47-4.27-0.37-8.14-2.47-12.16-3.94-7.13-2.59-14.84-3.22-22.18-5.18-3.09-0.82-6.13-1.89-9.26-2.54-1.39-0.29-2.8-0.5-4.12-1s-2.57-1.33-3.25-2.55c-0.47-0.86-0.63-1.86-0.56-2.84 0.07-0.97 0.36-1.92 0.74-2.83 0.77-1.8 1.9-3.46 2.49-5.32 0.88-2.75 0.52-5.72-0.14-8.53-0.65-2.8-1.6-5.55-1.89-8.41-0.13-1.27-0.13-2.57 0.17-3.82 0.29-1.25 0.88-2.45 1.81-3.34 1.2-1.15 2.88-1.73 4.56-1.89 1.67-0.16 3.35 0.06 5.01 0.3s3.34 0.5 5.01 0.42c1.68-0.07 3.39-0.51 4.7-1.54 1.3-1.02 2.12-2.53 2.59-4.09 0.47-1.57 0.62-3.2 0.81-4.82s0.43-3.26 1.06-4.77 1.69-2.9 3.17-3.64z" clip-path="url(#clip_foot_left)" fill="#f5bd0c" filter="url(#blur_foot_left_layer_2)"/>
|
||||
<path id="foot_left_glare" d="m51.2 188.21c2.25 4.06 3.62 8.72 5.85 12.82 2.05 3.77 4.38 7.65 6.46 11.12 0.93 1.55 3.09 3.93 5.27 7.62 1.98 3.34 3.98 8.01 5.1 9.58-0.64-1.84-1.96-6.77-3.54-10.28-1.47-3.28-3.19-5.15-4.24-6.92-2.08-3.47-4.33-6.6-6.47-9.91-2.95-4.57-5.2-9.68-8.43-14.03z" clip-path="url(#clip_foot_left)" fill="url(#fill_foot_left_glare)" filter="url(#blur_foot_left_glare)"/>
|
||||
</g>
|
||||
<g id="foot_right">
|
||||
<path id="foot_right_shadow" d="m198.7 215.61c-0.4 1.33-1.02 2.62-1.81 3.8-1.75 2.59-4.3 4.55-6.84 6.35-4.33 3.07-8.85 5.89-12.89 9.38-2.7 2.34-5.17 4.97-7.45 7.73-1.95 2.36-3.79 4.84-6.02 6.94-2.25 2.12-4.89 3.84-7.74 4.77-3.47 1.13-7.13 1.08-10.47 0.22-2.34-0.6-4.63-1.64-6.08-3.53s-1.92-4.44-2.09-6.94c-0.3-4.42 0.23-8.93 0.71-13.42 0.4-3.73 0.77-7.46 0.92-11.18 0.27-6.77-0.18-13.47-1.09-20.05-0.16-1.11-0.32-2.22-0.23-3.35 0.09-1.14 0.47-2.32 1.27-3.2 0.74-0.81 1.77-1.29 2.79-1.52 1.02-0.24 2.06-0.25 3.09-0.28 2.43-0.06 4.86-0.21 7.25 0.01 1.51 0.13 2.99 0.41 4.49 0.55 2.51 0.24 5.12 0.12 7.64-0.62 2.71-0.8 5.29-2.29 8.05-2.7 1.13-0.17 2.26-0.15 3.36 0.01 1.12 0.15 2.24 0.46 3.1 1.15 0.66 0.52 1.14 1.23 1.51 1.99 0.56 1.14 0.9 2.39 1.1 3.68 0.17 1.14 0.24 2.31 0.53 3.41 0.48 1.81 1.58 3.35 2.89 4.6 1.32 1.25 2.85 2.24 4.39 3.22 1.53 0.97 3.07 1.93 4.7 2.73 0.77 0.38 1.56 0.72 2.29 1.15 0.74 0.44 1.42 0.97 1.91 1.67 0.66 0.95 0.92 2.2 0.72 3.43z" clip-path="url(#clip_body)" fill="url(#fill_foot_right_shadow)" filter="url(#blur_foot_right_shadow)" opacity=".2"/>
|
||||
<path id="foot_right_base" d="m213.47 222.92c-2.26 2.68-5.4 4.45-8.53 6.05-5.33 2.71-10.86 5.1-15.87 8.37-3.36 2.19-6.46 4.76-9.36 7.53-2.48 2.37-4.83 4.9-7.61 6.91-2.81 2.03-6.05 3.5-9.48 4.01-0.95 0.14-1.9 0.21-2.86 0.21-3.24 0-6.48-0.78-9.46-2.08-2.7-1.17-5.3-2.86-6.86-5.36-1.56-2.52-1.92-5.59-1.92-8.56-0.01-5.23 0.96-10.41 1.87-15.57 0.76-4.29 1.48-8.58 1.95-12.91 0.85-7.86 0.84-15.81 0.28-23.71-0.1-1.32-0.21-2.65-0.01-3.96s0.74-2.62 1.74-3.48c0.93-0.8 2.17-1.16 3.4-1.22 1.22-0.07 2.44 0.12 3.65 0.3 2.85 0.42 5.73 0.74 8.52 1.48 1.76 0.46 3.48 1.08 5.23 1.56 2.94 0.79 6.01 1.17 9.02 0.82 3.25-0.38 6.41-1.6 9.68-1.52 1.34 0.03 2.67 0.28 3.95 0.69 1.3 0.41 2.59 1 3.55 1.98 0.73 0.74 1.24 1.67 1.62 2.64 0.57 1.44 0.88 2.98 1.01 4.52 0.11 1.37 0.09 2.76 0.35 4.11 0.43 2.21 1.6 4.24 3.04 5.97 1.45 1.74 3.18 3.21 4.91 4.66s3.46 2.89 5.32 4.16c0.87 0.6 1.77 1.16 2.6 1.81 0.83 0.66 1.59 1.42 2.11 2.34 0.45 0.81 0.69 1.72 0.69 2.65 0 0.52-0.07 1.04-0.23 1.56-0.45 1.43-1.28 2.82-2.3 4.04z" fill="url(#fill_foot_right_base)"/>
|
||||
<path d="m213.21 216.12c-0.53 1.33-1.28 2.58-2.22 3.67-2.07 2.42-4.93 4.01-7.78 5.44-4.88 2.44-9.92 4.58-14.5 7.52-3.06 1.97-5.9 4.28-8.55 6.78-2.26 2.13-4.41 4.41-6.95 6.21-2.57 1.83-5.53 3.14-8.65 3.6-3.8 0.56-7.72-0.16-11.25-1.67-2.46-1.06-4.84-2.56-6.27-4.83-1.42-2.26-1.75-5.02-1.75-7.69-0.02-4.71 0.87-9.37 1.71-14 0.7-3.85 1.36-7.71 1.78-11.6 0.76-7.08 0.73-14.22 0.25-21.32-0.08-1.19-0.17-2.39 0.01-3.57s0.67-2.35 1.57-3.13c0.85-0.73 1.99-1.05 3.11-1.1 1.11-0.06 2.22 0.12 3.33 0.28 2.61 0.38 5.23 0.67 7.78 1.33 1.61 0.42 3.18 0.98 4.78 1.4 2.68 0.72 5.49 1.06 8.24 0.74 2.97-0.34 5.85-1.44 8.83-1.37 1.23 0.03 2.44 0.26 3.61 0.62 1.19 0.37 2.37 0.9 3.25 1.78 0.66 0.67 1.11 1.51 1.48 2.38 0.53 1.29 0.89 2.67 0.91 4.07 0.03 1.46-0.28 2.92-0.09 4.37 0.16 1.17 0.66 2.28 1.3 3.28 0.63 1 1.4 1.91 2.17 2.81 1.48 1.75 2.96 3.53 4.82 4.87 2.11 1.53 4.62 2.43 6.8 3.85 0.65 0.43 1.28 0.91 1.74 1.54 0.78 1.06 0.98 2.5 0.54 3.74z" clip-path="url(#clip_foot_right)" fill="#cd8907" filter="url(#blur_foot_right_layer_1)"/>
|
||||
<path d="m212.91 214.61c-0.6 1.35-1.37 2.6-2.28 3.71-2.12 2.58-4.99 4.35-8 5.49-4.97 1.88-10.39 2.13-15.26 4.27-2.97 1.3-5.65 3.26-8.36 5.12-2.18 1.49-4.42 2.94-6.82 3.98-2.72 1.19-5.6 1.85-8.5 2.32-1.84 0.29-3.71 0.51-5.57 0.41s-3.72-0.54-5.37-1.49c-1.24-0.72-2.36-1.75-3.03-3.1-0.73-1.49-0.86-3.24-0.85-4.94 0.05-4.5 1.02-8.96 0.99-13.47-0.03-3.93-0.81-7.8-1.03-11.72-0.43-7.54 1.19-15.2-0.24-22.59-0.22-1.19-0.53-2.37-0.52-3.58 0.01-0.6 0.1-1.21 0.31-1.77 0.22-0.55 0.56-1.06 1.01-1.42 0.39-0.29 0.84-0.47 1.31-0.56 0.46-0.08 0.94-0.06 1.41 0.01 0.93 0.15 1.82 0.51 2.73 0.78 2.6 0.78 5.35 0.76 8 1.35 1.66 0.36 3.26 0.97 4.91 1.41 2.75 0.76 5.63 1.08 8.46 0.75 3.04-0.36 6.01-1.46 9.07-1.38 1.26 0.03 2.5 0.26 3.71 0.62s2.42 0.87 3.34 1.8c0.65 0.67 1.13 1.52 1.51 2.4 0.57 1.29 0.96 2.69 0.95 4.11-0.01 0.74-0.12 1.47-0.19 2.21-0.06 0.74-0.08 1.49 0.09 2.2 0.18 0.72 0.55 1.37 0.97 1.96s0.9 1.12 1.34 1.7c1.22 1.61 2.1 3.49 3.05 5.3s2.02 3.6 3.53 4.91c2.05 1.77 4.7 2.48 6.99 3.89 0.67 0.41 1.31 0.89 1.78 1.55 0.38 0.52 0.63 1.15 0.73 1.81 0.09 0.65 0.03 1.34-0.17 1.96z" clip-path="url(#clip_foot_right)" fill="#f5c021" filter="url(#blur_foot_right_layer_2)"/>
|
||||
<path id="foot_right_glare" d="m148.08 181.58c2.82-0.76 5.22 1.38 7.27 2.99 1.32 1.13 3.24 0.85 4.86 0.9 2.69-0.09 5.36 0.45 8.05 0.12 5.3-0.45 10.49-1.75 15.81-1.97 2.54-0.16 5.4-0.31 7.59 1.17 0.89 0.62 2.2 3.23 3.07 2.25-0.36-2.74-2.39-5.39-5.11-6.12-2.14-0.34-4.3 0.25-6.46 0.06-6.39-0.15-12.75-1.34-19.16-1-4.46 0.04-8.91-0.17-13.37-0.34-1.75-0.36-2.37 1.19-3.32 1.79 0.25 0.19 0.34 0.25 0.77 0.15z" clip-path="url(#clip_foot_right)" fill="url(#fill_foot_right_glare)" filter="url(#blur_foot_right_glare)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="wing_tip_right">
|
||||
<g id="wing_tip_right_shadow">
|
||||
<path id="wing_tip_right_shadow_lower" d="m185.49 187.61c-0.48-0.95-1.36-1.66-2.35-2.07-0.98-0.41-2.06-0.55-3.13-0.54-2.13 0.02-4.25 0.57-6.38 0.39-1.79-0.16-3.49-0.83-5.24-1.26-1.81-0.44-3.73-0.61-5.52-0.12-1.92 0.52-3.61 1.81-4.67 3.49-0.94 1.48-1.38 3.23-1.52 4.98s0.01 3.5 0.19 5.25c0.12 1.26 0.27 2.52 0.57 3.75 0.31 1.23 0.78 2.43 1.52 3.46 1.07 1.48 2.66 2.54 4.37 3.17 2.8 1.03 5.98 0.98 8.73-0.15 4.88-2.12 9.01-5.92 11.52-10.6 0.91-1.68 1.61-3.47 2.06-5.31 0.18-0.74 0.32-1.49 0.32-2.25 0.01-0.75-0.12-1.52-0.47-2.19z" clip-path="url(#clip_foot_right)" fill="url(#fill_wing_tip_right_shadow_lower)" filter="url(#blur_wing_tip_right_shadow_lower)" opacity=".35"/>
|
||||
<path id="wing_tip_right_shadow_upper" d="m185.49 184.89c-0.48-0.69-1.36-1.2-2.35-1.5-0.98-0.3-2.06-0.39-3.13-0.39-2.13 0.02-4.25 0.42-6.38 0.28-1.79-0.11-3.49-0.6-5.24-0.9-1.81-0.32-3.73-0.45-5.52-0.09-1.92 0.37-3.61 1.3-4.67 2.52-0.94 1.07-1.38 2.34-1.52 3.6s0.01 2.53 0.19 3.79c0.12 0.91 0.27 1.83 0.57 2.72 0.31 0.89 0.78 1.76 1.52 2.5 1.07 1.07 2.66 1.83 4.37 2.29 2.8 0.75 5.98 0.71 8.73-0.11 4.88-1.53 9.01-4.28 11.52-7.66 0.91-1.22 1.61-2.51 2.06-3.84 0.18-0.54 0.32-1.08 0.32-1.62 0.01-0.55-0.12-1.11-0.47-1.59z" clip-path="url(#clip_foot_right)" fill="url(#fill_wing_tip_right_shadow_upper)" filter="url(#blur_wing_tip_right_shadow_upper)" opacity=".35"/>
|
||||
</g>
|
||||
<path id="wing_tip_right_base" d="m189.55 178.72c-0.35-0.95-0.97-1.79-1.72-2.47s-1.64-1.2-2.57-1.6c-1.86-0.79-3.89-1.09-5.89-1.46-1.87-0.35-3.74-0.78-5.62-1.1-1.96-0.33-3.98-0.55-5.92-0.11-1.69 0.38-3.26 1.26-4.54 2.43s-2.28 2.63-3 4.21c-1.27 2.79-1.67 5.92-1.43 8.97 0.18 2.27 0.76 4.61 2.25 6.32 1.21 1.39 2.92 2.26 4.68 2.78 3.04 0.9 6.35 0.85 9.36-0.13 4.97-1.67 9.37-4.98 12.35-9.29 0.98-1.43 1.82-2.98 2.2-4.66 0.29-1.28 0.3-2.66-0.15-3.89z" fill="#020204"/>
|
||||
<g id="wing_tip_right_glare">
|
||||
<defs>
|
||||
<path id="path_wing_tip_right_glare" d="m168.89 171.07c-0.47 0.03-0.93 0.08-1.4 0.17-2.99 0.53-5.73 2.42-7.27 5.03-1.09 1.85-1.58 4.03-1.43 6.17 0.07-1.5 0.46-2.97 1.19-4.28 1.23-2.23 3.47-3.91 5.98-4.37 1.54-0.28 3.13-0.11 4.68 0.08 1.5 0.19 3 0.39 4.47 0.7 2.28 0.5 4.53 1.26 6.44 2.59 0.44 0.31 0.86 0.66 1.21 1.08 0.35 0.41 0.62 0.89 0.73 1.42 0.15 0.78-0.07 1.6-0.46 2.29-0.39 0.7-0.92 1.3-1.48 1.86-0.46 0.46-0.94 0.89-1.43 1.32 2.21-0.43 4.44-1.03 6.28-2.31 0.77-0.55 1.48-1.2 1.94-2.02 0.46-0.83 0.65-1.83 0.43-2.75-0.16-0.62-0.5-1.19-0.92-1.67s-0.93-0.87-1.45-1.24c-2.31-1.62-5.01-2.65-7.81-2.99-1.8-0.33-3.61-0.61-5.42-0.83-1.41-0.18-2.86-0.33-4.28-0.25z"/>
|
||||
</defs>
|
||||
<use clip-path="url(#clip_wing_tip_right)" fill="url(#fill_wing_tip_right_glare_1)" filter="url(#blur_wing_tip_right_glare)" href="#path_wing_tip_right_glare" xlink:href="#path_wing_tip_right_glare"/>
|
||||
<use clip-path="url(#clip_wing_tip_right)" fill="url(#fill_wing_tip_right_glare_2)" filter="url(#blur_wing_tip_right_glare)" href="#path_wing_tip_right_glare" xlink:href="#path_wing_tip_right_glare"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="face">
|
||||
<g id="eyes">
|
||||
<g id="eye_left">
|
||||
<path id="eyeball_left" d="m84.45 38.28c-1.53 0.08-3 0.79-4.12 1.84-1.13 1.05-1.92 2.43-2.41 3.88-0.97 2.92-0.75 6.08-0.53 9.15 0.2 2.77 0.41 5.6 1.45 8.18 0.52 1.3 1.25 2.51 2.22 3.51 0.97 0.99 2.2 1.76 3.55 2.09 1.26 0.32 2.62 0.26 3.86-0.13 1.25-0.4 2.38-1.11 3.32-2.02 1.36-1.33 2.27-3.07 2.8-4.9s0.68-3.75 0.65-5.66c-0.04-2.38-0.35-4.77-1.09-7.03-0.75-2.26-1.94-4.4-3.6-6.11-0.8-0.83-1.72-1.55-2.75-2.06-1.04-0.51-2.2-0.8-3.35-0.74z" fill="url(#fill_eyeball_left)"/>
|
||||
<g id="pupil_left">
|
||||
<path id="pupil_left_base" d="m80.75 50.99c-0.32 1.94-0.33 3.97 0.33 5.81 0.44 1.22 1.17 2.33 2.05 3.28 0.57 0.62 1.23 1.18 1.99 1.55 0.77 0.37 1.65 0.52 2.48 0.32 0.76-0.19 1.42-0.68 1.91-1.29s0.82-1.34 1.05-2.09c0.69-2.21 0.58-4.62-0.11-6.83-0.49-1.61-1.32-3.16-2.6-4.24-0.62-0.52-1.34-0.93-2.12-1.11-0.78-0.19-1.63-0.14-2.36 0.19-0.81 0.37-1.44 1.07-1.85 1.86s-0.62 1.67-0.77 2.55z" fill="#020204"/>
|
||||
<path id="pupil_left_glare" d="m84.84 49.59c0.21 0.55 0.91 0.75 1.3 1.19 0.37 0.42 0.76 0.87 0.97 1.4 0.39 1.01-0.39 2.51 0.43 3.23 0.25 0.22 0.77 0.23 1.02 0 0.99-0.9 0.77-2.71 0.38-3.99-0.36-1.15-1.23-2.25-2.31-2.8-0.5-0.26-1.25-0.47-1.68-0.11-0.27 0.24-0.24 0.74-0.11 1.08z" clip-path="url(#clip_pupil_left)" fill="url(#fill_pupil_left_glare)" filter="url(#blur_pupil_left_glare)"/>
|
||||
</g>
|
||||
<path id="eyelid_left" d="m81.14 44.46c2.32-1.38 5.13-1.7 7.82-1.45 2.68 0.26 5.27 1.04 7.87 1.75 1.91 0.52 3.84 1 5.63 1.84 1.78 0.84 3.44 2.08 4.43 3.8 0.16 0.27 0.29 0.56 0.46 0.83s0.37 0.52 0.62 0.71 0.57 0.32 0.88 0.3c0.16-0.01 0.32-0.05 0.45-0.13 0.14-0.08 0.26-0.2 0.33-0.34 0.08-0.16 0.11-0.35 0.1-0.53s-0.05-0.36-0.1-0.54c-0.65-2.37-2.19-4.38-3.35-6.55-0.7-1.3-1.28-2.66-1.98-3.96-2.43-4.45-6.42-7.94-10.95-10.21s-9.59-3.36-14.65-3.65c-5.86-0.35-11.73 0.35-17.51 1.37-2.51 0.44-5.06 0.96-7.27 2.21-1.11 0.62-2.13 1.42-2.92 2.42-0.8 0.99-1.36 2.18-1.55 3.44-0.17 1.22 0.01 2.47 0.44 3.62 0.42 1.15 1.08 2.2 1.86 3.15 1.54 1.91 3.53 3.39 5.36 5.03 1.83 1.63 3.52 3.44 5.57 4.79 1.02 0.68 2.13 1.24 3.31 1.57s2.44 0.42 3.64 0.17c1.24-0.25 2.4-0.86 3.41-1.64 1.01-0.77 1.88-1.7 2.71-2.66 1.66-1.93 3.21-4.04 5.39-5.34z" clip-path="url(#clip_eye_left)" fill="url(#fill_eyelid_left)"/>
|
||||
<path id="eyebrow_left" d="m90.77 36.57c2.16 2.02 3.76 4.52 4.85 7.16-0.48-2.91-1.23-5.26-3.13-7.16-1.16-1.09-2.49-2.05-3.98-2.72-1.32-0.59-2.77-0.96-3.61-0.97-0.83-0.02-1.03 0-1.2 0.01-0.18 0.01-0.31 0.01 0.23 0.08 0.54 0.06 1.75 0.39 3.05 0.97s2.62 1.54 3.79 2.63z" fill="url(#fill_eyebrow_left)" filter="url(#blur_eyebrow_left)"/>
|
||||
</g>
|
||||
<g id="eye_right">
|
||||
<path id="eyeball_right" d="m111.61 38.28c-2.39 1.65-4.4 3.94-5.38 6.68-1.24 3.45-0.77 7.31 0.43 10.77 1.22 3.55 3.27 6.93 6.36 9.06 1.54 1.07 3.33 1.8 5.19 2.02 1.87 0.22 3.8-0.09 5.47-0.95 2.02-1.06 3.57-2.91 4.53-4.98 0.96-2.08 1.37-4.37 1.5-6.66 0.16-2.9-0.12-5.86-1.08-8.61-1.04-2.99-2.92-5.75-5.58-7.47-1.32-0.86-2.83-1.45-4.4-1.67s-3.19-0.05-4.67 0.52c-0.84 0.33-1.62 0.78-2.37 1.29z" fill="url(#fill_eyeball_right)"/>
|
||||
<g id="pupil_right">
|
||||
<path id="pupil_right_base" d="m117.14 45.52c-0.9 0.06-1.78 0.37-2.55 0.85-0.76 0.48-1.41 1.13-1.92 1.88-1.03 1.49-1.48 3.31-1.55 5.12-0.05 1.35 0.1 2.72 0.55 4s1.2 2.47 2.25 3.33c1.07 0.89 2.42 1.42 3.81 1.49 1.39 0.06 2.79-0.34 3.93-1.13 0.91-0.63 1.64-1.5 2.16-2.48 0.52-0.97 0.84-2.05 0.98-3.15 0.25-1.93-0.03-3.95-0.93-5.69-0.89-1.74-2.41-3.17-4.24-3.84-0.8-0.29-1.65-0.44-2.49-0.38z" fill="#020204"/>
|
||||
<path id="pupil_right_glare" d="m122.71 53.36c1-1-0.71-3.65-2.05-4.74-0.97-0.78-3.78-1.61-3.66-0.75 0.12 0.85 1.39 1.95 2.23 2.79 1.05 1.03 3 3.18 3.48 2.7z" clip-path="url(#clip_pupil_right)" fill="url(#fill_pupil_right_glare)" filter="url(#blur_pupil_right_glare)"/>
|
||||
</g>
|
||||
<path id="eyelid_right" d="m102.56 47.01c2.06-1.71 4.45-3.01 7-3.8 5.25-1.62 11.2-0.98 15.84 1.97 1.6 1.01 3.03 2.27 4.52 3.45 1.48 1.17 3.06 2.27 4.85 2.9 0.97 0.34 2 0.54 3.02 0.43 0.92-0.09 1.81-0.44 2.57-0.96 0.76-0.53 1.4-1.23 1.88-2.02 0.96-1.58 1.27-3.5 1.1-5.34-0.33-3.69-2.41-6.94-4.15-10.21-0.55-1.02-1.07-2.06-1.73-3.01-2.01-2.93-5.23-4.86-8.6-5.99s-6.93-1.54-10.46-1.98c-1.58-0.2-3.17-0.41-4.74-0.22-1.81 0.22-3.51 0.95-5.28 1.4-0.84 0.22-1.69 0.37-2.52 0.61s-1.65 0.57-2.33 1.11c-0.98 0.79-1.6 1.98-1.87 3.21-0.27 1.24-0.21 2.52-0.01 3.77 0.39 2.5 1.33 4.93 1.24 7.46-0.06 1.73-0.61 3.44-0.54 5.17 0.02 0.51 0.12 1.55 0.21 2.05z" clip-path="url(#clip_eye_right)" fill="url(#fill_eyelid_right)"/>
|
||||
<path id="eyebrow_right" d="m119.93 31.18c-0.41 0.52-0.78 1.08-1.07 1.7 1.85 0.4 3.61 1.16 5.19 2.21 3.06 2.03 5.38 4.99 7.01 8.29 0.38-0.42 0.72-0.87 1.02-1.37-1.64-3.44-4-6.55-7.16-8.65-1.52-1-3.21-1.77-4.99-2.18z" fill="url(#fill_eyebrow_right)" filter="url(#blur_eyebrow_right)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="beak">
|
||||
<g id="beak_shadow">
|
||||
<path id="beak_shadow_lower" d="m81.12 89.33c1.47 4.26 4.42 7.89 7.92 10.72 1.16 0.95 2.39 1.82 3.76 2.43 1.36 0.62 2.87 0.97 4.36 0.84 1.46-0.12 2.85-0.7 4.13-1.42s2.46-1.59 3.7-2.37c2.12-1.35 4.39-2.44 6.6-3.64 2.65-1.45 5.23-3.1 7.46-5.14 1.03-0.93 1.98-1.95 3.11-2.75 1.13-0.81 2.49-1.39 3.87-1.29 1.04 0.07 2.01 0.51 3.03 0.73 0.51 0.11 1.03 0.16 1.55 0.08 0.51-0.08 1.01-0.29 1.37-0.67 0.44-0.46 0.64-1.12 0.61-1.76-0.02-0.63-0.24-1.25-0.54-1.81-0.59-1.13-1.49-2.1-1.89-3.31-0.36-1.08-0.29-2.24-0.26-3.37 0.03-1.14 0.01-2.32-0.51-3.33-0.4-0.76-1.07-1.37-1.83-1.77-0.76-0.41-1.62-0.62-2.48-0.7-1.72-0.16-3.44 0.18-5.17 0.27-2.28 0.13-4.58-0.15-6.87-0.02-2.85 0.18-5.65 1-8.51 1.01-3.26 0.01-6.52-1.06-9.74-0.55-1.39 0.22-2.71 0.72-4.03 1.16-1.33 0.45-2.7 0.84-4.1 0.82-1.59-0.03-3.13-0.58-4.72-0.69-0.79-0.06-1.6 0-2.35 0.28-0.74 0.28-1.41 0.79-1.78 1.5-0.21 0.4-0.31 0.86-0.33 1.31-0.02 0.46 0.04 0.91 0.15 1.36 0.22 0.88 0.63 1.71 0.96 2.55 1.2 3.07 1.46 6.42 2.53 9.53z" clip-path="url(#clip_body)" fill-opacity=".25882" filter="url(#blur_beak_shadow_lower)"/>
|
||||
<path id="beak_shadow_upper" d="m77.03 77.2c2.85 1.76 5.41 3.93 7.56 6.39 1.99 2.29 3.68 4.89 6.29 6.58 1.83 1.2 4.04 1.87 6.28 2.08 2.63 0.24 5.29-0.15 7.83-0.84 2.35-0.63 4.62-1.53 6.7-2.71 3.97-2.25 7.28-5.55 11.65-7.03 0.95-0.33 1.94-0.56 2.86-0.96 0.92-0.39 1.79-0.99 2.23-1.83 0.42-0.82 0.4-1.75 0.54-2.64 0.15-0.96 0.48-1.88 0.66-2.83s0.2-1.96-0.24-2.83c-0.37-0.72-1.04-1.29-1.81-1.66-0.77-0.36-1.64-0.52-2.51-0.56-1.72-0.08-3.43 0.33-5.16 0.47-2.28 0.19-4.58-0.08-6.87-0.01-2.85 0.08-5.66 0.67-8.51 0.8-3.25 0.14-6.49-0.34-9.74-0.44-1.41-0.05-2.83-0.03-4.21 0.2-1.39 0.22-2.75 0.65-3.92 1.37-1.14 0.69-2.07 1.64-3.11 2.45-0.52 0.41-1.08 0.78-1.68 1.07-0.61 0.28-1.28 0.48-1.96 0.51-0.35 0.01-0.71-0.01-1.05 0.04-0.59 0.08-1.13 0.39-1.47 0.83-0.34 0.45-0.47 1.02-0.36 1.55z" clip-path="url(#clip_body)" filter="url(#blur_beak_shadow_upper)" opacity=".3"/>
|
||||
</g>
|
||||
<path id="beak_base" d="m91.66 58.53c1.53-1.71 2.57-3.8 4.03-5.56 0.73-0.88 1.58-1.69 2.57-2.26s2.15-0.89 3.29-0.79c1.27 0.11 2.46 0.74 3.39 1.61s1.62 1.97 2.17 3.12c0.53 1.11 0.95 2.28 1.71 3.24 0.81 1.02 1.94 1.71 2.97 2.52 0.51 0.4 1.01 0.83 1.41 1.34 0.41 0.51 0.72 1.1 0.86 1.74 0.13 0.65 0.06 1.33-0.16 1.95-0.23 0.62-0.61 1.18-1.09 1.64-0.95 0.92-2.25 1.42-3.56 1.6-2.62 0.37-5.27-0.41-7.92-0.34-2.67 0.08-5.29 1.02-7.97 0.93-1.33-0.05-2.69-0.38-3.79-1.14-0.55-0.39-1.03-0.88-1.38-1.45-0.34-0.57-0.55-1.23-0.58-1.9-0.02-0.64 0.13-1.28 0.39-1.86 0.25-0.59 0.61-1.12 1.01-1.62 0.81-0.99 1.8-1.81 2.65-2.77z" fill="url(#fill_beak_base)"/>
|
||||
<g id="mandible_lower">
|
||||
<path id="mandible_lower_base" d="m77.14 75.05c0.06 0.26 0.15 0.5 0.28 0.73 0.23 0.38 0.57 0.69 0.93 0.95 0.36 0.27 0.75 0.49 1.13 0.72 2.01 1.27 3.65 3.04 5.11 4.92 1.95 2.52 3.68 5.31 6.29 7.14 1.84 1.3 4.04 2.03 6.28 2.26 2.63 0.26 5.29-0.16 7.83-0.91 2.35-0.69 4.62-1.66 6.7-2.95 3.97-2.44 7.28-6.02 11.65-7.63 0.95-0.35 1.94-0.6 2.86-1.03 0.92-0.44 1.79-1.08 2.23-2 0.42-0.88 0.4-1.9 0.54-2.87 0.15-1.03 0.48-2.03 0.66-3.06s0.2-2.13-0.24-3.08c-0.37-0.78-1.04-1.4-1.81-1.79-0.77-0.4-1.64-0.58-2.51-0.62-1.72-0.08-3.43 0.36-5.16 0.52-2.28 0.21-4.58-0.09-6.87-0.02-2.85 0.09-5.66 0.73-8.51 0.87-3.25 0.15-6.49-0.35-9.74-0.48-1.41-0.06-2.83-0.04-4.22 0.2-1.39 0.23-2.75 0.71-3.91 1.51-1.13 0.78-2.03 1.84-3.07 2.74-0.52 0.45-1.08 0.86-1.7 1.16-0.61 0.3-1.29 0.49-1.98 0.47-0.35-0.01-0.72-0.06-1.05 0.04-0.21 0.07-0.4 0.2-0.56 0.35-0.16 0.16-0.29 0.34-0.41 0.52-0.29 0.42-0.54 0.87-0.75 1.34z" fill="url(#fill_mandible_lower_base)"/>
|
||||
<path id="mandible_lower_glare" d="m89.9 78.56c-0.33 1.37-0.13 2.87 0.56 4.11 0.68 1.24 1.84 2.2 3.19 2.65 1.7 0.57 3.62 0.29 5.21-0.54 0.93-0.48 1.77-1.16 2.3-2.06 0.27-0.44 0.46-0.94 0.53-1.46 0.06-0.51 0.02-1.05-0.16-1.54-0.2-0.53-0.56-1-0.99-1.37-0.44-0.37-0.95-0.64-1.5-0.82-1.08-0.36-2.77-0.66-3.91-0.68-2.02-0.04-4.9 0.34-5.23 1.71z" clip-path="url(#clip_mandible_lower)" fill="#d9b30d" filter="url(#blur_mandible_lower_glare)"/>
|
||||
</g>
|
||||
<g id="mandible_upper">
|
||||
<path id="mandible_upper_shadow" d="m84.31 67.86c-1.16 0.68-2.27 1.43-3.36 2.2-0.57 0.41-1.15 0.84-1.45 1.47-0.21 0.44-0.26 0.94-0.27 1.43 0 0.5 0.03 0.99-0.04 1.48-0.04 0.33-0.13 0.66-0.14 0.99-0.01 0.17 0 0.34 0.04 0.5 0.05 0.16 0.13 0.32 0.24 0.44 0.15 0.16 0.35 0.26 0.56 0.32s0.42 0.09 0.64 0.14c1.01 0.24 1.89 0.86 2.66 1.56 0.77 0.69 1.47 1.48 2.28 2.13 2.18 1.78 5.07 2.52 7.89 2.56 2.82 0.05 5.61-0.54 8.36-1.16 2.16-0.49 4.32-0.99 6.39-1.76 3.2-1.18 6.16-2.96 8.72-5.19 1.17-1.01 2.26-2.12 3.57-2.94 1.15-0.73 2.44-1.21 3.62-1.9 0.11-0.06 0.21-0.13 0.3-0.2 0.1-0.08 0.18-0.18 0.24-0.28 0.09-0.19 0.09-0.42 0.03-0.62s-0.18-0.38-0.31-0.55c-0.15-0.18-0.31-0.34-0.49-0.5-1.23-1.05-2.89-1.43-4.51-1.56-1.61-0.12-3.24-0.03-4.83-0.3-1.5-0.25-2.92-0.81-4.37-1.27-1.52-0.49-3.07-0.87-4.64-1.13-3.71-0.61-7.52-0.49-11.19 0.27-3.49 0.73-6.87 2.05-9.94 3.87z" clip-path="url(#clip_mandible_lower)" fill="#604405" filter="url(#blur_mandible_upper_shadow)"/>
|
||||
<path id="mandible_upper_base" d="m83.94 63.95c-1.66 1.12-3.16 2.49-4.43 4.04-0.72 0.89-1.38 1.86-1.74 2.94-0.29 0.86-0.39 1.76-0.57 2.65-0.07 0.33-0.15 0.66-0.14 1 0 0.16 0.02 0.33 0.07 0.5 0.05 0.16 0.14 0.31 0.25 0.43 0.2 0.2 0.47 0.31 0.74 0.37 0.28 0.05 0.56 0.06 0.84 0.09 1.25 0.15 2.4 0.75 3.44 1.47 1.04 0.71 2 1.55 3.07 2.22 2.35 1.49 5.16 2.15 7.95 2.26 2.78 0.11 5.56-0.31 8.3-0.86 2.17-0.43 4.33-0.95 6.39-1.76 3.16-1.25 6.01-3.16 8.72-5.19 1.24-0.92 2.46-1.87 3.57-2.94 0.37-0.37 0.74-0.74 1.14-1.08 0.4-0.33 0.85-0.62 1.35-0.78 0.76-0.24 1.58-0.17 2.37-0.04 0.59 0.1 1.18 0.23 1.78 0.21 0.3-0.02 0.6-0.07 0.88-0.18s0.54-0.28 0.73-0.52c0.25-0.3 0.38-0.7 0.38-1.09 0-0.4-0.12-0.79-0.32-1.13-0.4-0.68-1.09-1.14-1.81-1.46-0.99-0.44-2.06-0.65-3.11-0.91-3.23-0.78-6.37-1.93-9.34-3.41-1.48-0.73-2.92-1.54-4.37-2.32-1.5-0.8-3.02-1.57-4.64-2.07-3.64-1.1-7.6-0.74-11.19 0.51-3.98 1.38-7.58 3.84-10.31 7.05z" fill="url(#fill_mandible_upper_base)"/>
|
||||
<path id="mandible_upper_glare" d="m109.45 64.75c-0.2-0.24-0.48-0.42-0.78-0.51s-0.62-0.09-0.93-0.04c-0.62 0.11-1.18 0.44-1.7 0.8-1.47 1.01-2.77 2.26-3.91 3.64-1.5 1.83-2.74 3.94-3.16 6.27-0.07 0.39-0.11 0.8-0.07 1.19 0.05 0.4 0.2 0.79 0.49 1.07 0.24 0.25 0.58 0.4 0.92 0.45 0.35 0.05 0.71 0 1.04-0.11 0.66-0.22 1.21-0.69 1.74-1.15 2.87-2.58 5.47-5.66 6.51-9.38 0.1-0.37 0.19-0.75 0.19-1.14s-0.1-0.78-0.34-1.09z" clip-path="url(#clip_mandible_upper)" fill="#f6da4a" filter="url(#blur_mandible_upper_glare)"/>
|
||||
<path id="naris_left" d="m92.72 59.06c-0.77-0.25-2.03 1.1-1.62 1.79 0.11 0.19 0.46 0.43 0.7 0.3 0.35-0.19 0.64-0.89 1.02-1.16 0.25-0.18 0.2-0.84-0.1-0.93z" fill="url(#fill_naris_left)" filter="url(#blur_naris_left)" opacity=".8"/>
|
||||
<path id="naris_right" d="m102.56 59.42c0.2 0.64 1.23 0.53 1.83 0.84 0.52 0.27 0.94 0.86 1.53 0.88 0.56 0.01 1.44-0.2 1.51-0.76 0.09-0.73-0.98-1.2-1.67-1.47-0.89-0.34-2.03-0.52-2.86-0.06-0.19 0.11-0.4 0.36-0.34 0.57z" fill="url(#fill_naris_right)" filter="url(#blur_naris_right)" opacity=".8"/>
|
||||
</g>
|
||||
<path id="beak_corner" d="m129.27 69.15a2.42 3.1 16.94 0 1-2.81 3.04 2.42 3.1 16.94 0 1-2.12-3.04 2.42 3.1 16.94 0 1 2.81-3.05 2.42 3.1 16.94 0 1 2.12 3.05z" clip-path="url(#clip_beak)" fill="url(#fill_beak_corner)" filter="url(#blur_beak_corner)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 45 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" stroke="#35bf5c" stroke-width="4" viewBox="0 0 14 14">
|
||||
<path d="M9 2H2V14 2M7 5v9M12 0V14"/>
|
||||
</svg>
|
After Width: | Height: | Size: 140 B |
|
@ -0,0 +1,73 @@
|
|||
Packaging Cahute
|
||||
================
|
||||
|
||||
Cahute is constituted of a static library, a set of utilities, and a
|
||||
set of udev rules. Due to the last element having to be installed for both,
|
||||
only the following package organisations are available:
|
||||
|
||||
* Having one package for both the static library and utilities.
|
||||
* Having one package for the static library, either a package for all utilities
|
||||
or a package for each utility, and a package for installing the udev rules,
|
||||
of which all previous package depend.
|
||||
|
||||
For more about the rationale behind this document, consult the
|
||||
`Archlinux CMake packaging guidelines`_.
|
||||
|
||||
Preparing the dependencies
|
||||
--------------------------
|
||||
|
||||
Cahute depends on the following, build-only dependencies:
|
||||
|
||||
* cmake_ >= 3.16;
|
||||
* `GNU Make`_, `pkg-config`_, and other C compilation and linking utilities.
|
||||
|
||||
It also depends on the following build and runtime dependencies:
|
||||
|
||||
* libusb_;
|
||||
* SDL_ >= 2.0 (for ``p7screen``).
|
||||
|
||||
Producing the distribution directory
|
||||
------------------------------------
|
||||
|
||||
You first need to retrieve the source directory, named "cahute-|version|",
|
||||
using one of the following methods:
|
||||
|
||||
* You can download the latest source package at
|
||||
https://ftp.cahuteproject.org/releases\ :
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
curl -o cahute-|version|.tar.gz https\://ftp.cahuteproject.org/releases/cahute-|version|.tar.gz
|
||||
tar xvaf cahute-|version|.tar.gz
|
||||
|
||||
* You can clone the repository and checkout the tag corresponding to the
|
||||
release:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
git clone https\://gitlab.com/cahuteproject/cahute.git cahute-|version|
|
||||
(cd cahute-|version| && git checkout -f |version|)
|
||||
|
||||
Now that you have the source directory, you can build it using the following
|
||||
commands:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
cmake -B build -S cahute-|version| -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake --build build
|
||||
|
||||
Once this is done, you can produce the distribution directory ``dist/``
|
||||
using the following command::
|
||||
|
||||
DESTDIR=./dist cmake --install build
|
||||
|
||||
Your distribution directory is ready; from there, the instructions are
|
||||
specific to your distribution. Good luck!
|
||||
|
||||
.. _Archlinux CMake packaging guidelines:
|
||||
https://wiki.archlinux.org/title/CMake_package_guidelines
|
||||
.. _cmake: https://cmake.org/
|
||||
.. _GNU Make: https://www.gnu.org/software/make/
|
||||
.. _pkg-config: https://git.sr.ht/~kaniini/pkgconf
|
||||
.. _SDL: https://www.libsdl.org/
|
||||
.. _libusb: https://libusb.info/
|
|
@ -0,0 +1,64 @@
|
|||
.. _issue-reporting-guide:
|
||||
|
||||
Reporting a vulnerability or issue
|
||||
==================================
|
||||
|
||||
If you have identified that Cahute or any of its utilities does not work
|
||||
properly, or would like to suggest a feature or evolution, there are
|
||||
different procedures depending on the issue.
|
||||
|
||||
.. warning::
|
||||
|
||||
Once your issue is up or sent, **please check on it every few days at
|
||||
least, or leave a way for the maintainers to contact you without
|
||||
giving up their privacy** (i.e. no phone numbers, social network
|
||||
profile or instant messaging address); an e-mail address is fine.
|
||||
|
||||
An issue reported by someone who can't answer once additional details
|
||||
are required from them is an issue that gets closed and has wasted
|
||||
everyone's time and efforts.
|
||||
|
||||
.. warning::
|
||||
|
||||
For any type of issue, due to the fact that Cahute is free software
|
||||
maintained by people on their free time, there is no guarantee of any
|
||||
delay, or even of a response or that the issue won't be closed due to
|
||||
lack of availability on the maintainers' part.
|
||||
|
||||
Note however that this warning is worst case scenario, and hopefully,
|
||||
it won't come to that for any correctly reported issue.
|
||||
|
||||
Reporting a vulnerability
|
||||
-------------------------
|
||||
|
||||
If your issue has security implications, e.g. if it allows a malicious
|
||||
device to access the host and/or execute arbitrary code without authorisation,
|
||||
please send an e-mail to Thomas Touhey, the maintainer of Cahute,
|
||||
at <security@cahuteproject.org>.
|
||||
|
||||
.. note::
|
||||
|
||||
Please only use this e-mail address if there is security implications
|
||||
to your demand. If you are not sure if your issue qualifies or not,
|
||||
send it anyway; use your best judgment.
|
||||
|
||||
.. _report-other-issues:
|
||||
|
||||
Reporting any other issue or evolution request
|
||||
----------------------------------------------
|
||||
|
||||
For all other issues, you can create an issue on the `issue tracker at
|
||||
Gitlab`_.
|
||||
|
||||
If you are effectively reporting a bug in your issue, please include the
|
||||
following elements:
|
||||
|
||||
* System and version (e.g. Debian 14, Ubuntu 22.04 LTS, Windows 11 Pro, ...).
|
||||
* Architecture (x64, ARM, ...).
|
||||
* Cahute version (e.g. 0.1, 1.2.1, ...).
|
||||
* If the issue regards a communication protocol: the calculator model and
|
||||
OS version, e.g. Graph 90+E with OS 03.60.2202.
|
||||
* **Steps to reproduce the issue**, on both the host and any device that
|
||||
was implicated in the operation. (The order is important!)
|
||||
|
||||
.. _Issue tracker at Gitlab: https://gitlab.com/cahuteproject/cahute/-/issues
|
|
@ -0,0 +1,9 @@
|
|||
Header reference
|
||||
================
|
||||
|
||||
This section presents the code reference, by header.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
headers/cahute
|
|
@ -0,0 +1,13 @@
|
|||
``<cahute.h>`` -- Main header for Cahute
|
||||
========================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cahute/cdefs
|
||||
cahute/detection
|
||||
cahute/error
|
||||
cahute/link
|
||||
cahute/logging
|
||||
cahute/osversion
|
||||
cahute/picture
|
|
@ -0,0 +1,289 @@
|
|||
``<cahute/cdefs.h>`` -- Basic definitions for Cahute
|
||||
====================================================
|
||||
|
||||
This header declares basic definitions for Cahute.
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
.. c:macro:: CAHUTE_PREREQ(MAJOR, MINOR)
|
||||
|
||||
Macro that returns whether the current version of Cahute is compatible
|
||||
with the provided version of Cahute.
|
||||
|
||||
For example, ``CAHUTE_PREREQ(2, 4)`` checks if the current version of
|
||||
Cahute is compatible with version 2.4.
|
||||
|
||||
.. c:macro:: OF(...)
|
||||
|
||||
Macro for defining parameter definitions in a function declaration.
|
||||
For example::
|
||||
|
||||
int my_function OF((int arg1, char const *arg2));
|
||||
|
||||
This is present because in K&R C (pre-C89), function declarations did
|
||||
not include parameters, i.e. the function declaration above would need
|
||||
to render as the following::
|
||||
|
||||
int my_function();
|
||||
|
||||
.. c:macro:: CAHUTE_EXTERN(TYPE)
|
||||
|
||||
Macro to use in Cahute function declarations, surrounding the return type,
|
||||
for compatibility. For example::
|
||||
|
||||
CAHUTE_EXTERN(int) my_function(int arg1, char const *arg2);
|
||||
|
||||
This is used to add calling conventions or other platform-specific options
|
||||
in some cases, such as, on 16-bit x86 where the calling convention was
|
||||
best described explicitely.
|
||||
|
||||
Example outputs of the above are the following::
|
||||
|
||||
int my_function(int arg1, char const *arg2); /* Default. */
|
||||
|
||||
_stdcall int my_function(int arg1, char const *arg2); /* WINAPI x86 */
|
||||
|
||||
int __cdecl my_function(int arg1, char const *arg2); /* GCC x86 */
|
||||
|
||||
extern __declspec(dllexport) int my_function(int arg1, char const *arg2); /* Borland C */
|
||||
|
||||
.. c:macro:: CAHUTE_LOCAL(TYPE)
|
||||
|
||||
Macro to use in Cahute function definitions, surrounding the return type,
|
||||
as opposed to :c:macro:`CAHUTE_EXTERN`. For example::
|
||||
|
||||
CAHUTE_LOCAL(int) my_local_utility(int arg1, char const *arg2);
|
||||
|
||||
For now, this only produces the following output::
|
||||
|
||||
static int my_local_utility(int arg1, char const *arg2);
|
||||
|
||||
.. c:macro:: CAHUTE_INLINE(TYPE)
|
||||
|
||||
Macro to use in inlinable local Cahute function definitions, surrounding
|
||||
the return type. This macro extends on :c:macro:`CAHUTE_LOCAL`'s meaning,
|
||||
by making the function inlinable if the compiler is so inclined.
|
||||
|
||||
For example::
|
||||
|
||||
CAHUTE_INLINE(int) my_tiny_utility(int arg1, char const *arg2);
|
||||
|
||||
This can then use compiler-specific functions, such as GCC's
|
||||
``always_inline`` attribute; see `GCC function attributes`_ for
|
||||
more information.
|
||||
|
||||
.. c:macro:: CAHUTE_LOCAL_DATA(TYPE)
|
||||
|
||||
Macro to use in local data in Cahute source files, surrounding the
|
||||
variable type, for example::
|
||||
|
||||
CAHUTE_LOCAL_DATA(char const *) my_string = "hello, world";
|
||||
|
||||
For now, this only produces the following output::
|
||||
|
||||
static char const * my_string = "hello, world";
|
||||
|
||||
.. c:macro:: CAHUTE_DEPRECATED
|
||||
|
||||
Function attribute, placed before the return type and
|
||||
:c:macro:`CAHUTE_EXTERN`, that indicates that the compiler should
|
||||
warn that the function is deprecated when compiling a user program or
|
||||
library.
|
||||
|
||||
For example::
|
||||
|
||||
CAHUTE_DEPRECATED int my_deprecated_function(int a, int b);
|
||||
|
||||
.. c:macro:: CAHUTE_WUR
|
||||
|
||||
Function attribute, placed before the return type and
|
||||
:c:macro:`CAHUTE_EXTERN`, that indicates that the compiler should
|
||||
**w**\ arn in case of **u**\ nused **r**\ esult, i.e. if the caller
|
||||
does not store nor process the resulting value from the function.
|
||||
|
||||
For example::
|
||||
|
||||
CAHUTE_WUR resource *create_resource(int a, int b);
|
||||
|
||||
.. c:macro:: CAHUTE_NNPTR(NAME)
|
||||
|
||||
Function parameter attribute that indicate that the passed value should
|
||||
not be ``NULL``. It must be used in both the function declaration
|
||||
and definition. For example::
|
||||
|
||||
int my_function(char const CAHUTE_NNPTR(my_string))
|
||||
|
||||
Calling this with an explicitely NULL pointer will raise a compiler
|
||||
warning or error.
|
||||
|
||||
This may resolve as::
|
||||
|
||||
int my_function(char const *my_string); /* Default. */
|
||||
int my_function(char const my_string[static 1]); /* C99. */
|
||||
|
||||
For maximum compatibility, this macro must be used with
|
||||
:c:macro:`CAHUTE_NONNULL`.
|
||||
|
||||
.. c:macro:: CAHUTE_NONNULL(INDEXES)
|
||||
|
||||
Indicate, as an attribute, that one or more of the function arguments
|
||||
should not be passed as NULL. For example::
|
||||
|
||||
int my_function(int *a, int *b, int *c) CAHUTE_NONNULL((1, 3));
|
||||
|
||||
Calling ``my_function`` with a NULL pointer for ``a`` or ``c`` will raise
|
||||
a compiler warning or error.
|
||||
|
||||
This may resolve as::
|
||||
|
||||
int my_function(int *a, int *b, int *c); /* Default. */
|
||||
int my_function(int *a, int *b, int *c) __attribute__((nonnull (1, 3))); /* Pre-C99 GCC. */
|
||||
|
||||
For maximum compatibility, this macro must be used with
|
||||
:c:macro:`CAHUTE_NNPTR`.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIu8
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u8` in decimal form,
|
||||
e.g. ``hhu``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIu16
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u16` in decimal form,
|
||||
e.g. ``hu``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIu32
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u32` in decimal form,
|
||||
e.g. ``u``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIuSIZE
|
||||
|
||||
printf specifier for displaying ``size_t`` in decimal form, e.g. ``zu``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIx8
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u8` in lowercase
|
||||
hexadecimal form, e.g. ``hhx``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIx16
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u16` in lowercase
|
||||
hexadecimal form, e.g. ``hx``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIx32
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u32` in lowercase
|
||||
hexadecimal form, e.g. ``x``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIxSIZE
|
||||
|
||||
printf specifier for displaying ``size_t`` in lowercase hexadecimal form,
|
||||
e.g. ``zx``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIX8
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u8` in uppercase
|
||||
hexadecimal form, e.g. ``hhX``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIX16
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u16` in uppercase
|
||||
hexadecimal form, e.g. ``hX``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIX32
|
||||
|
||||
printf specifier for displaying :c:type:`cahute_u32` in uppercase
|
||||
hexadecimal form, e.g. ``X``.
|
||||
|
||||
.. c:macro:: CAHUTE_PRIXSIZE
|
||||
|
||||
printf specifier for displaying ``size_t`` in uppercase hexadecimal form,
|
||||
e.g. ``zX``.
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
.. c:type:: cahute_u8
|
||||
|
||||
Unsigned 8-bit integer type.
|
||||
|
||||
Available printf specifiers for this type are :c:macro:`CAHUTE_PRIu8`,
|
||||
:c:macro:`CAHUTE_PRIx8` and :c:macro:`CAHUTE_PRIX8`.
|
||||
|
||||
.. c:type:: cahute_u16
|
||||
|
||||
Unsigned 16-bit integer type.
|
||||
|
||||
Available printf specifiers for this type are :c:macro:`CAHUTE_PRIu16`,
|
||||
:c:macro:`CAHUTE_PRIx16` and :c:macro:`CAHUTE_PRIX16`.
|
||||
|
||||
.. c:type:: cahute_u32
|
||||
|
||||
Unsigned 32-bit integer type.
|
||||
|
||||
Available printf specifiers for this type are :c:macro:`CAHUTE_PRIu32`,
|
||||
:c:macro:`CAHUTE_PRIx32` and :c:macro:`CAHUTE_PRIX32`.
|
||||
|
||||
Function declarations
|
||||
---------------------
|
||||
|
||||
.. c:function:: cahute_u16 cahute_be16toh(cahute_u16 value)
|
||||
|
||||
Convert a 16-bit unsigned integer from big endian to host endianness.
|
||||
|
||||
:param value: 16-bit unsigned integer in big endian.
|
||||
:return: 16-bit unsigned integer in host endianness.
|
||||
|
||||
.. c:function:: cahute_u16 cahute_le16toh(cahute_u16 value)
|
||||
|
||||
Convert a 16-bit unsigned integer from little endian to host endianness.
|
||||
|
||||
:param value: 16-bit unsigned integer in little endian.
|
||||
:return: 16-bit unsigned integer in host endianness.
|
||||
|
||||
.. c:function:: cahute_u32 cahute_be32toh(cahute_u32 value)
|
||||
|
||||
Convert a 32-bit unsigned integer from big endian to host endianness.
|
||||
|
||||
:param value: 32-bit unsigned integer in big endian.
|
||||
:return: 32-bit unsigned integer in host endianness.
|
||||
|
||||
.. c:function:: cahute_u32 cahute_le32toh(cahute_u32 value)
|
||||
|
||||
Convert a 32-bit unsigned integer from little endian to host endianness.
|
||||
|
||||
:param value: 32-bit unsigned integer in little endian.
|
||||
:return: 32-bit unsigned integer in host endianness.
|
||||
|
||||
.. c:function:: cahute_u16 cahute_htobe16(cahute_u16 value)
|
||||
|
||||
Convert a 16-bit unsigned integer from host endianness to big endian.
|
||||
|
||||
:param value: 16-bit unsigned integer in host endianness.
|
||||
:return: 16-bit unsigned integer in big endian.
|
||||
|
||||
.. c:function:: cahute_u16 cahute_htole16(cahute_u16 value)
|
||||
|
||||
Convert a 16-bit unsigned integer from host endianness to little endian.
|
||||
|
||||
:param value: 16-bit unsigned integer in host endianness.
|
||||
:return: 16-bit unsigned integer in little endian.
|
||||
|
||||
.. c:function:: cahute_u32 cahute_htobe32(cahute_u32 value)
|
||||
|
||||
Convert a 32-bit unsigned integer from host endianness to big endian.
|
||||
|
||||
:param value: 32-bit unsigned integer in host endianness.
|
||||
:return: 32-bit unsigned integer in big endian.
|
||||
|
||||
.. c:function:: cahute_u32 cahute_htole32(cahute_u32 value)
|
||||
|
||||
Convert a 32-bit unsigned integer from host endianness to little endian.
|
||||
|
||||
:param value: 32-bit unsigned integer in host endianness.
|
||||
:return: 32-bit unsigned integer in little endian.
|
||||
|
||||
.. _GCC function attributes:
|
||||
https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
|
|
@ -0,0 +1,114 @@
|
|||
``<cahute/detection.h>`` -- Device detection for Cahute
|
||||
=======================================================
|
||||
|
||||
This header declares device detection related utilities for Cahute.
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
``CAHUTE_USB_DETECTION_ENTRY_TYPE_*`` are constants representing the type of
|
||||
device identified using the USB descriptor.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN
|
||||
|
||||
The device is an fx-9860G or compatible calculator, using Protocol 7.00
|
||||
directly through bulk transfers.
|
||||
|
||||
Note that the fx-CG calculators sometimes use identify as an fx-9860G
|
||||
for os updating or some types of screenstreaming.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_DETECTION_ENTRY_TYPE_SCSI
|
||||
|
||||
The device is an fx-CG or compatible calculator, using SCSI with extensions
|
||||
to communicate using Protocol 7.00 through vendor-specific commands.
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
.. c:struct:: cahute_serial_detection_entry
|
||||
|
||||
Available serial port that can be opened using
|
||||
:c:func:`cahute_open_serial_link`.
|
||||
|
||||
.. c:member:: char const *cahute_serial_detection_entry_name
|
||||
|
||||
Null-terminated name or path of the serial port.
|
||||
|
||||
.. c:struct:: cahute_usb_detection_entry
|
||||
|
||||
Available USB device that can be opened using
|
||||
:c:func:`cahute_open_usb_link`.
|
||||
|
||||
.. c:member:: int cahute_usb_detection_entry_bus
|
||||
|
||||
USB bus number of the entry.
|
||||
|
||||
.. c:member:: int cahute_usb_detection_entry_address
|
||||
|
||||
USB address number of the entry.
|
||||
|
||||
.. c:member:: int cahute_usb_detection_entry_type
|
||||
|
||||
Entry type, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN
|
||||
|
||||
The device is a Protocol 7.00 device over bulk.
|
||||
|
||||
See :ref:`protocol-seven` for more details.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_DETECTION_ENTRY_TYPE_SCSI
|
||||
|
||||
The device is a UAS (USB-Attached SCSI) device with proprietary
|
||||
extensions to communicate using Protocol 7.00.
|
||||
|
||||
See :ref:`protocol-ums` for more details.
|
||||
|
||||
See :ref:`usb-detection` for more information.
|
||||
|
||||
.. c:type:: int (*cahute_detect_serial_entry_func)(void *cookie, \
|
||||
cahute_serial_detection_entry const *entry)
|
||||
|
||||
Function that can be called back with a serial detection entry.
|
||||
See :c:func:`cahute_detect_serial` for more information.
|
||||
|
||||
.. c:type:: int (*cahute_detect_usb_entry_func)(void *cookie, \
|
||||
cahute_usb_detection_entry const *entry)
|
||||
|
||||
Function that can be called back with a USB detection entry.
|
||||
See :c:func:`cahute_detect_usb` for more information.
|
||||
|
||||
Function declarations
|
||||
---------------------
|
||||
|
||||
.. c:function:: int cahute_detect_serial( \
|
||||
cahute_detect_serial_entry_func *func, void *cookie)
|
||||
|
||||
Detect available serial devices.
|
||||
|
||||
For every found entry, the provided function is called with its cookie
|
||||
and details regarding the serial entry, represented by its
|
||||
``entry`` parameter of :c:type:`cahute_serial_detection_entry` type.
|
||||
|
||||
If the callback returns a non-zero value, it signals the current function
|
||||
to stop and return the :c:macro:`CAHUTE_ERROR_INT` error.
|
||||
|
||||
:param func: Function to call with every entry.
|
||||
:param cookie: Cookie to pass to the function.
|
||||
:return: The error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_detect_usb(cahute_detect_usb_entry_func *func, \
|
||||
void *cookie)
|
||||
|
||||
Detect available USB devices.
|
||||
|
||||
For every found entry, the provided function is called with its cookie
|
||||
and details regarding the USB entry, represented by its
|
||||
``entry`` parameter of :c:type:`cahute_usb_detection_entry` type.
|
||||
|
||||
If the callback returns a non-zero value, it signals the current function
|
||||
to stop and return the :c:macro:`CAHUTE_ERROR_INT` error.
|
||||
|
||||
:param func: Function to call with every entry.
|
||||
:param cookie: Cookie to pass to the function.
|
||||
:return: The error, or 0 if the operation was successful.
|
|
@ -0,0 +1,88 @@
|
|||
``<cahute/error.h>`` -- Error definitions for Cahute
|
||||
====================================================
|
||||
|
||||
This header declares error values and utilities for Cahute.
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
.. c:macro:: CAHUTE_OK
|
||||
|
||||
Error returned in case of success.
|
||||
This is set to ``0``, so that in order to check if a Cahute function has
|
||||
yielded an error, you can do the following:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
if (cahute_do_thing(1, 2)) {
|
||||
fprintf(stderr, "An error has occurred.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_UNKNOWN
|
||||
|
||||
Error raised if the cause of the error is unknown.
|
||||
|
||||
The logs can be investigated for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_IMPL
|
||||
|
||||
Error raised if a required feature or code path was unimplemented.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_ALLOC
|
||||
|
||||
Error raised if a memory allocation has failed.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_PRIV
|
||||
|
||||
Error raised if a system privilege error has been encountered.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_INT
|
||||
|
||||
Error raised if, for a function taking a callback and calling it
|
||||
with every iteration, said callback has returned ``1`` on a given
|
||||
iteration, meaning the iteration was *INTerrupted*.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_SIZE
|
||||
|
||||
Error raised if an incoming message was too big for the corresponding
|
||||
internal buffers.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_NOT_FOUND
|
||||
|
||||
Error code raised if a device could not be found using the provided
|
||||
identification (name, path, or bus identification).
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_TOO_MANY
|
||||
|
||||
Error raised if only a single device was expected, but multiple were
|
||||
found.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_INCOMPAT
|
||||
|
||||
Error raised if a device was not suitable to be opened to be used by
|
||||
a link.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_GONE
|
||||
|
||||
Error raised if a device with which communication was previously
|
||||
established is no longer accessible.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_TIMEOUT
|
||||
|
||||
Error raised if a timeout has been encountered on an I/O operation.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_CORRUPT
|
||||
|
||||
Error raised if an incoming packet had invalid format, or an invalid
|
||||
checksum.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_IRRECOV
|
||||
|
||||
Error raised if the link was previously deemed irrecoverable, and as such,
|
||||
the current operation could not be executed.
|
||||
|
||||
.. c:macro:: CAHUTE_ERROR_NOOW
|
||||
|
||||
Error raised if overwrite was requested and rejected by either us or
|
||||
the calculator.
|
|
@ -0,0 +1,614 @@
|
|||
``<cahute/link.h>`` -- Calculator link resource and methods for Cahute
|
||||
======================================================================
|
||||
|
||||
This header declares link-related utilities for Cahute.
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
.. c:struct:: cahute_device_info
|
||||
|
||||
Device information.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_flags
|
||||
|
||||
Flags for the link information.
|
||||
|
||||
.. c:macro:: CAHUTE_DEVICE_INFO_FLAG_PREPROG
|
||||
|
||||
Preprogrammed ROM information available.
|
||||
|
||||
.. c:macro:: CAHUTE_DEVICE_INFO_FLAG_BOOTCODE
|
||||
|
||||
Bootcode information available.
|
||||
|
||||
.. c:macro:: CAHUTE_DEVICE_INFO_FLAG_OS
|
||||
|
||||
OS information available.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_rom_capacity
|
||||
|
||||
Preprogrammed ROM capacity, in KiB.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_PREPROG`
|
||||
flag is set.
|
||||
|
||||
.. c:member:: cahute_os_version cahute_device_info_rom_version
|
||||
|
||||
Preprogrammed ROM version.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_PREPROG`
|
||||
flag is set.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_flash_rom_capacity
|
||||
|
||||
Flash ROM capacity, in KiB.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_ram_capacity
|
||||
|
||||
RAM capacity, in KiB.
|
||||
|
||||
.. c:member:: cahute_version cahute_device_info_bootcode_version
|
||||
|
||||
Bootcode version.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_BOOTCODE`
|
||||
flag is set.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_bootcode_offset
|
||||
|
||||
Bootcode offset.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_BOOTCODE`
|
||||
flag is set.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_bootcode_size
|
||||
|
||||
Bootcode size, in KiB.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_BOOTCODE`
|
||||
flag is set.
|
||||
|
||||
.. c:member:: cahute_version cahute_device_info_os_version
|
||||
|
||||
OS version.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_OS` flag
|
||||
is set.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_os_offset
|
||||
|
||||
OS offset.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_OS` flag
|
||||
is set.
|
||||
|
||||
.. c:member:: unsigned long cahute_device_info_os_size
|
||||
|
||||
OS size, in KiB.
|
||||
|
||||
Only available if the :c:macro:`CAHUTE_DEVICE_INFO_FLAG_OS` flag
|
||||
is set.
|
||||
|
||||
.. c:member:: char const *cahute_device_info_product_id
|
||||
|
||||
Null-terminated product identifier, up to 16 characters.
|
||||
|
||||
.. c:member:: char const *cahute_device_info_username
|
||||
|
||||
Null-terminated username, up to 20 characters long.
|
||||
|
||||
.. c:member:: char const *cahute_device_info_organisation
|
||||
|
||||
Null-terminated organisation, up to 20 characters long.
|
||||
|
||||
.. c:member:: char const *cahute_device_info_hwid
|
||||
|
||||
Null-terminated hardware identifier, up to 8 characters.
|
||||
|
||||
.. c:member:: char const *cahute_device_info_cpuid
|
||||
|
||||
Null-terminated hardware platform identifier, up to 16 characters.
|
||||
|
||||
.. c:struct:: cahute_frame
|
||||
|
||||
Screenstreaming frame details for screenstreaming.
|
||||
|
||||
.. c:member:: int cahute_frame_width
|
||||
|
||||
Width of the frame, in pixels.
|
||||
|
||||
.. c:member:: int cahute_frame_height
|
||||
|
||||
Height of the frame, in pixels.
|
||||
|
||||
.. c:member:: int cahute_frame_format
|
||||
|
||||
Format of the frame, as a ``CAHUTE_PICTURE_FORMAT_*`` constant.
|
||||
See :ref:`header-cahute-picture` for more information.
|
||||
|
||||
.. c:member:: cahute_u8 const *cahute_frame_data
|
||||
|
||||
Frame contents encoded with the format described above.
|
||||
|
||||
.. c:struct:: cahute_storage_entry
|
||||
|
||||
Entry when listing the contents of a storage device or directory.
|
||||
|
||||
.. c:member:: char const *cahute_storage_entry_directory
|
||||
|
||||
If the entry is a directory, the name of the directory.
|
||||
|
||||
If the entry is a file, the optional name of the directory in
|
||||
which the file is present; this can be set to ``NULL`` if the
|
||||
file is present at root.
|
||||
|
||||
.. c:member:: char const *cahute_storage_entry_name
|
||||
|
||||
If the entry is a directory, this is set to ``NULL``.
|
||||
|
||||
If the entry is a file, the file name.
|
||||
|
||||
.. c:member:: unsigned long cahute_storage_entry_size
|
||||
|
||||
Size in bytes of the file.
|
||||
|
||||
.. c:struct:: cahute_link
|
||||
|
||||
Link to a calculator, that can be used to run operations on the
|
||||
calculator, or receive data such as screenstreaming data.
|
||||
|
||||
This type is opaque, and such resources must be created using
|
||||
:c:func:`cahute_open_usb_link` or :c:func:`cahute_open_serial_link`.
|
||||
|
||||
.. c:type:: int (cahute_process_frame_func)(void *cookie, \
|
||||
cahute_frame const *frame)
|
||||
|
||||
Function that can be called when a frame has been received in a
|
||||
screenstreaming mode.
|
||||
|
||||
See :c:func:`cahute_receive_screen` for more information.
|
||||
|
||||
.. c:type:: int (cahute_confirm_overwrite_func)(void *cookie)
|
||||
|
||||
Function that can be called to confirm overwrite.
|
||||
|
||||
See :c:func:`cahute_send_file_to_storage` for more information.
|
||||
|
||||
.. c:type:: int (cahute_list_storage_entry_func)(void *cookie, \
|
||||
cahute_storage_list_entry const *entry)
|
||||
|
||||
Function that can be called for every storage device entry.
|
||||
|
||||
See :c:func:`cahute_list_storage_entries` for more information.
|
||||
|
||||
.. c:type:: int (cahute_progress_func)(void *cookie, unsigned long step,\
|
||||
unsigned long total)
|
||||
|
||||
Function that can be called to display progress, when step ``step`` out
|
||||
of ``total`` has just finished.
|
||||
|
||||
See :c:func:`cahute_send_file_to_storage` and
|
||||
:c:func:`cahute_request_file_from_storage` for more information.
|
||||
|
||||
Function declarations
|
||||
---------------------
|
||||
|
||||
.. c:function:: int cahute_open_serial_link(cahute_link **linkp, \
|
||||
unsigned long flags, char const *name, unsigned long speed)
|
||||
|
||||
Open a link over a serial modem.
|
||||
|
||||
.. warning::
|
||||
|
||||
In case of error, the value of ``*linkp`` mustn't be used nor freed.
|
||||
|
||||
Since serial links do not offer any metadata, the protocol to use on the
|
||||
serial link must be selected manually, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_PROTOCOL_SEVEN
|
||||
|
||||
Use Protocol 7.00.
|
||||
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
Since the number of stop bits may be selectable on the calculator, it
|
||||
can also be selected manually, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_STOP_ONE
|
||||
|
||||
Use 1 stop bit.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_STOP_TWO
|
||||
|
||||
Use 2 stop bits (*by default*).
|
||||
|
||||
Since the parity may also be selectable on the calculator, it can also
|
||||
be selected manually, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_PARITY_OFF
|
||||
|
||||
Disable parity checks (*by default*).
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_PARITY_EVEN
|
||||
|
||||
Use even parity checks.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_PARITY_ODD
|
||||
|
||||
Use odd parity checks.
|
||||
|
||||
.. note::
|
||||
|
||||
fx-9860G calculators and derivatives, i.e. the ones you will be the
|
||||
most likely to encounter, use protocol 7.00 with 2 stop bits and
|
||||
no parity when establishing a new connection.
|
||||
|
||||
The LINK app on such calculators does not allow to change these
|
||||
settings, and the only way for the link to use different settings
|
||||
is if the connection has already been established and command
|
||||
:ref:`seven-command-02` was issued to change the serial link
|
||||
parameters for the current connection.
|
||||
|
||||
If the device uses XON/XOFF software control, it can also be selected
|
||||
manually, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_XONXOFF_DISABLE
|
||||
|
||||
Disable XON/XOFF software control (*by default*).
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_XONXOFF_ENABLE
|
||||
|
||||
Enable XON/XOFF software control.
|
||||
|
||||
If the device uses DTR/RTS and the cable may support it, it can also be
|
||||
selected manually, amongst the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_DTRRTS_DISABLE
|
||||
|
||||
Disable DTR/RTS (*by default*).
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_DTRRTS_ENABLE
|
||||
|
||||
Enable DTR/RTS.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_DTRRTS_HANDSHAKE
|
||||
|
||||
Enable DTR/RTS, and require a DTR/RTS handshake to be done.
|
||||
|
||||
Protocol-specific behaviour can be tweaked using the following flags:
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_NOCHECK
|
||||
|
||||
If this flag is provided, the initial handshake will not be
|
||||
done when the link is established on the underlying medium.
|
||||
|
||||
This flag is mostly useful when resuming a connection initiated by
|
||||
another process, or when the passive process does not require or
|
||||
implement the initial handshake.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_NODISC
|
||||
|
||||
If this flag is provided, command :ref:`seven-command-01` is
|
||||
not issued once the link is established to get the device information.
|
||||
|
||||
This flag is mostly useful when dealing with bootcode or custom
|
||||
link implementations that may not have implemented this command.
|
||||
It is not recommended when communicating with the LINK application
|
||||
since it enables Cahute to predict which commands will be
|
||||
unavailable without crashing the link.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_NOTERM
|
||||
|
||||
If this flag is provided, the terminate flow is not run when
|
||||
the link is closed.
|
||||
|
||||
This flag is mostly useful to let the connection still opened for
|
||||
other processes to run commands. Combined with
|
||||
:c:macro:`CAHUTE_SERIAL_NOCHECK`, it allows running multiple shell
|
||||
commands on the same connection.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_SERIAL_OHP
|
||||
|
||||
If this flag is provided, the calculator is assumed to use the link
|
||||
for screenstreaming purposes.
|
||||
|
||||
For example, with the fx-9860G and compatible, this prompts the link
|
||||
to use Protocol 7.00 Screenstreaming instead of Protocol 7.00.
|
||||
|
||||
See :ref:`protocol-seven-ohp` for more information.
|
||||
|
||||
:param linkp: The pointer to set the opened link to.
|
||||
:param flags: The flags to set to the serial link.
|
||||
:param name: The name or path of the serial link to open.
|
||||
:param speed: The speed (in bauds) to open the serial link with, or ``0``
|
||||
to select the default serial speed.
|
||||
:return: The error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_open_usb_link(cahute_link **linkp, \
|
||||
unsigned long flags, int bus, int address)
|
||||
|
||||
Open a link with a USB device.
|
||||
|
||||
.. warning::
|
||||
|
||||
In case of error, the value of ``*linkp`` mustn't be used nor freed.
|
||||
|
||||
The protocol to use is determined using the USB device metadata.
|
||||
See :ref:`usb-detection` for more information.
|
||||
|
||||
Protocol-specific behaviour can be tweaked using the following flags:
|
||||
|
||||
.. c:macro:: CAHUTE_USB_NOCHECK
|
||||
|
||||
If this flag is provided, the initial handshake will not be
|
||||
done when the link is established on the underlying medium.
|
||||
|
||||
This flag is mostly useful when resuming a connection initiated by
|
||||
another process, or when the passive process does not require or
|
||||
implement the initial handshake.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_NODISC
|
||||
|
||||
If this flag is provided, command :ref:`seven-command-01` is
|
||||
not issued once the link is established to get the device information.
|
||||
|
||||
This flag is mostly useful when dealing with bootcode or custom
|
||||
link implementations that may not have implemented this command.
|
||||
It is not recommended when communicating with the LINK application
|
||||
since it enables Cahute to predict which commands will be
|
||||
unavailable without crashing the link.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_NOTERM
|
||||
|
||||
If this flag is provided, the terminate flow is not run when
|
||||
the link is closed.
|
||||
|
||||
This flag is mostly useful to let the connection still opened for
|
||||
other processes to run commands. Combined with
|
||||
:c:macro:`CAHUTE_USB_NOCHECK`, it allows running multiple shell
|
||||
commands on the same connection.
|
||||
|
||||
It is only effective when using protocol 7.00.
|
||||
See :ref:`protocol-seven` for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_USB_OHP
|
||||
|
||||
If this flag is provided, the calculator is assumed to use the link
|
||||
for screenstreaming purposes.
|
||||
|
||||
For example, with the fx-9860G and compatible, this prompts the link
|
||||
to use Protocol 7.00 Screenstreaming instead of Protocol 7.00.
|
||||
|
||||
See :ref:`protocol-seven-ohp` for more information.
|
||||
|
||||
:param linkp: The pointer to set the opened link to.
|
||||
:param flags: The flags to set to the serial link.
|
||||
:param bus: The bus number of the USB calculator to open a link with.
|
||||
:param address: The device number of the calculator to open a link with.
|
||||
:return: The error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: void cahute_close_link(cahute_link *link)
|
||||
|
||||
Close and free a link.
|
||||
|
||||
:param link: The link to close.
|
||||
|
||||
.. c:function:: int cahute_get_device_info(cahute_link *link, \
|
||||
cahute_device_info **infop)
|
||||
|
||||
Gather information on the device (calculator or other).
|
||||
|
||||
.. warning::
|
||||
|
||||
In all cases, ``*infop`` **musn't be freed**.
|
||||
In case of error, ``*infop`` mustn't be used.
|
||||
|
||||
:param link: The link on which to gather information.
|
||||
:param infop: The pointer to set to the information to.
|
||||
:return: The error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_negotiate_serial_params(cahute_link *link, \
|
||||
unsigned long flags, unsigned long speed)
|
||||
|
||||
Negotiate new parameters for a serial link, and update the medium
|
||||
parameters to these.
|
||||
|
||||
The accepted flags here are among ``CAHUTE_SERIAL_STOP_*`` and
|
||||
``CAHUTE_SERIAL_PARITY_*``.
|
||||
|
||||
:param link: Link to which to define the new attributes.
|
||||
:param flags: New flags to set to the serial link.
|
||||
:param speed: New speed to set to the serial link.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_receive_screen(cahute_link *link, \
|
||||
cahute_process_frame_func *callback, void *cookie)
|
||||
|
||||
Receive screen continuously, using screenstreaming, and call the provided
|
||||
function for every received frame.
|
||||
|
||||
If the provided function returns any non-zero value, the process is
|
||||
interrupted.
|
||||
|
||||
:param link: Link with which to receive screen frames.
|
||||
:param callback: Function to call for every received frame.
|
||||
:param cookie: Cookie to provide to the function on every call.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_request_storage_capacity(cahute_link *link, \
|
||||
char const *storage, unsigned long *capacityp)
|
||||
|
||||
Request the currently available capacity on the provided storage device.
|
||||
|
||||
If this function returns an error, the contents of ``*capacityp`` is
|
||||
left intact, and may be undefined.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param storage: Name of the storage device for which to get the
|
||||
currently available capacity.
|
||||
:param capacityp: Pointer to the capacity to fill.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_send_file_to_storage(cahute_link *link, \
|
||||
unsigned long flags, char const *directory, char const *name, \
|
||||
char const *storage, FILE *filep, \
|
||||
cahute_confirm_overwrite_func *overwrite_func, void *overwrite_cookie, \
|
||||
cahute_progress_func *progress_func, void *progress_cookie)
|
||||
|
||||
Send a file to a storage device on the calculator.
|
||||
|
||||
.. note::
|
||||
|
||||
The provided ``filep`` parameter will be used for reading and
|
||||
**seeking**, in order to estimate the file size.
|
||||
|
||||
If an overwrite confirmation function is provided and the calculator
|
||||
requests confirmation for overwriting, said function is called. Then:
|
||||
|
||||
* If the function returns ``0``, the overwrite is rejected, therefore
|
||||
the file is not sent.
|
||||
* If the function returns any other value, the overwrite is confirmed,
|
||||
and the function transfers the file over.
|
||||
|
||||
Flags that can be set to this function are the following:
|
||||
|
||||
.. c:macro:: CAHUTE_SEND_FILE_FLAG_FORCE
|
||||
|
||||
If this flag is set, overwrite is forced without using the
|
||||
callback functions.
|
||||
|
||||
.. c:macro:: CAHUTE_SEND_FILE_FLAG_OPTIMIZE
|
||||
|
||||
If this flag is set, the available capacity in the targeted storage
|
||||
is requested. If it is not considered enough to store the file, an
|
||||
optimize command will be issued beforehand.
|
||||
|
||||
See :ref:`seven-send-file-to-storage` for the use case with Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param flags: Flags for the function.
|
||||
:param directory: Name of the directory in which to place the file,
|
||||
or ``NULL`` if the file should be placed at root.
|
||||
:param name: Name of the file in the target storage device.
|
||||
:param storage: Name of the storage device on which to place the file.
|
||||
:param filep: Standard FILE pointer to read file data and estimate
|
||||
file size from.
|
||||
:param overwrite_func: Pointer to the overwrite function to call.
|
||||
If this is set to ``NULL``, the overwrite will be systematically
|
||||
rejected if requested by the calculator.
|
||||
:param overwrite_cookie: Cookie to pass to the overwrite
|
||||
confirmation function.
|
||||
:param progress_func: Pointer to the optional progress function to call
|
||||
once for every step in the transfer process.
|
||||
:param progress_cookie: Cookie to pass to the progress function.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_request_file_from_storage(cahute_link *link, \
|
||||
char const *directory, char const *name, char const *storage, \
|
||||
FILE *filep, cahute_progress_func *progress_func, void *progress_cookie)
|
||||
|
||||
Request a file from a storage device on the calculator.
|
||||
|
||||
See :ref:`seven-request-file-from-storage` for the use case with
|
||||
Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param directory: Name of the directory from which to request the file,
|
||||
or ``NULL`` if the file should be placed at root.
|
||||
:param name: Name of the file to request.
|
||||
:param storage: Name of the storage device from which to request the file.
|
||||
:param filep: Standard FILE pointer to write file data.
|
||||
:param progress_func: Pointer to the optional progress function to call
|
||||
once for every step in the transfer process.
|
||||
:param progress_cookie: Cookie to pass to the progress function.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_copy_file_on_storage(cahute_link *link, \
|
||||
char const *source_directory, char const *source_name, \
|
||||
char const *target_directory, char const *target_name, char const *storage)
|
||||
|
||||
Copy a file on a storage device on the calculator.
|
||||
|
||||
See :ref:`seven-copy-file-on-storage` for the use case with
|
||||
Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param source_directory: Name of the directory in which to retrieve
|
||||
the source file.
|
||||
:param source_name: Name of the source file to copy.
|
||||
:param target_directory: Name of the directory in which to create
|
||||
the copy.
|
||||
:param target_name: Name of the copy.
|
||||
:param storage: Name of the storage device on which to copy.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_delete_file_from_storage(cahute_link *link, \
|
||||
char const *directory, char const *name, char const *storage)
|
||||
|
||||
Delete a file from a storage device on the calculator.
|
||||
|
||||
See :ref:`seven-delete-file-on-storage` for the use case with
|
||||
Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param directory: Name of the directory from which to delete the file,
|
||||
or ``NULL`` if the file should be placed at root.
|
||||
:param name: Name of the file to delete.
|
||||
:param storage: Name of the storage device from which to delete the file.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_list_storage_entries(cahute_link *link, \
|
||||
char const *storage, cahute_list_storage_entry_func *callback, \
|
||||
void *cookie)
|
||||
|
||||
List files and directories on a storage device on the calculator.
|
||||
|
||||
For every entry, the callback function is called. If it returns a value
|
||||
other than ``0``, the file listing is interrupted.
|
||||
|
||||
See :ref:`seven-list-files-on-storage` for the use case with
|
||||
Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param storage: Storage on which to list files and directories.
|
||||
:param func: Function to call back with every found entry.
|
||||
:param cookie: Cookie to pass to the function.
|
||||
:return: Error, or 0 if the operation was unsuccessful.
|
||||
|
||||
.. c:function:: int cahute_reset_storage(cahute_link *link, \
|
||||
char const *storage)
|
||||
|
||||
Request a reset of the provided storage device by the calculator.
|
||||
|
||||
See :ref:`seven-reset-storage` for the use case with Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param storage: Name of the storage device.
|
||||
:return: Error, or 0 if the operation was successful.
|
||||
|
||||
.. c:function:: int cahute_optimize_storage(cahute_link *link, \
|
||||
char const *storage)
|
||||
|
||||
Request optimization for the provided storage device by the calculator.
|
||||
|
||||
See :ref:`seven-optimize-storage` for the use case with Protocol 7.00.
|
||||
|
||||
:param link: Link to the device.
|
||||
:param storage: Name of the storage device.
|
||||
:return: Error, or 0 if the operation was successful.
|
|
@ -0,0 +1,41 @@
|
|||
``<cahute/logging.h>`` -- Logging control for Cahute
|
||||
====================================================
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
.. c:macro:: CAHUTE_LOGLEVEL_INFO
|
||||
|
||||
Constant representing the ``info`` logging level; see :ref:`logging`
|
||||
for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_LOGLEVEL_WARNING
|
||||
|
||||
Constant representing the ``warning`` logging level; see :ref:`logging`
|
||||
for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_LOGLEVEL_ERROR
|
||||
|
||||
Constant representing the ``error`` logging level; see :ref:`logging`
|
||||
for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_LOGLEVEL_FATAL
|
||||
|
||||
Constant representing the ``fatal`` logging level; see :ref:`logging`
|
||||
for more information.
|
||||
|
||||
.. c:macro:: CAHUTE_LOGLEVEL_NONE
|
||||
|
||||
Constant representing the special ``none`` logging level; see
|
||||
:ref:`logging` for more information.
|
||||
|
||||
Function declarations
|
||||
---------------------
|
||||
|
||||
.. c:function:: int cahute_get_log_level()
|
||||
|
||||
:return: The current logging level.
|
||||
|
||||
.. c:function:: void cahute_set_log_level(int level)
|
||||
|
||||
:param level: The logging level to set as the current one.
|
|
@ -0,0 +1,108 @@
|
|||
``<cahute/osversion.h>`` -- CASIO OS version format utilities for Cahute
|
||||
========================================================================
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
``CAHUTE_VERSION_ZONE_*`` represent geographical zones
|
||||
(markets) for which the software is produced.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_NONE
|
||||
|
||||
International.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_AUS
|
||||
|
||||
Australia.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_FR
|
||||
|
||||
France.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_NAM
|
||||
|
||||
North America.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_CH
|
||||
|
||||
China.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_ZONE_SING
|
||||
|
||||
Singapour.
|
||||
|
||||
``CAHUTE_VERSION_MATH_*`` represent the available math
|
||||
input/output features for the software.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_MATH_SLIM
|
||||
|
||||
Slim.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_MATH_ALL
|
||||
|
||||
All features (fx-9860GII-2).
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_MATH_REDUCED
|
||||
|
||||
Reduced features (fx-7400GII)
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_MATH_NONE
|
||||
|
||||
No features.
|
||||
|
||||
``CAHUTE_VERSION_STATUS_*`` represent the build type for
|
||||
the software.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_STATUS_STANDARD
|
||||
|
||||
Standard build.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_STATUS_INDEV
|
||||
|
||||
Special / Development build.
|
||||
|
||||
``CAHUTE_VERSION_PLATFORM_*`` represent the hardware platform
|
||||
on which the software runs.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_PLATFORM_BASIC
|
||||
|
||||
SH7337 / SH7355.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_PLATFORM_SPECIAL
|
||||
|
||||
SH7305.
|
||||
|
||||
.. c:macro:: CAHUTE_VERSION_PLATFORM_PRIZM
|
||||
|
||||
SH7305 (Prizm).
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
.. c:struct:: cahute_os_version
|
||||
|
||||
CASIO OS version structure, determined from a version string.
|
||||
|
||||
.. c:member:: int cahute_version_major
|
||||
|
||||
Major version.
|
||||
|
||||
.. c:member:: int cahute_version_minor
|
||||
|
||||
Minor version.
|
||||
|
||||
.. c:member:: cahute_version_zone cahute_version_zone
|
||||
|
||||
Geographical zone (market).
|
||||
|
||||
.. c:member:: cahute_version_math cahute_version_math
|
||||
|
||||
Available math I/O features.
|
||||
|
||||
.. c:member:: cahute_version_status cahute_version_status
|
||||
|
||||
Build type.
|
||||
|
||||
.. c:member:: cahute_version_platform cahute_version_platform
|
||||
|
||||
Hardware platform.
|
|
@ -0,0 +1,26 @@
|
|||
.. _header-cahute-picture:
|
||||
|
||||
``<cahute/picture.h>`` -- Picture format related utilities for Cahute
|
||||
=====================================================================
|
||||
|
||||
Macro definitions
|
||||
-----------------
|
||||
|
||||
``CAHUTE_PICTURE_FORMAT_*`` are constants representing how a given
|
||||
picture's data is encoded.
|
||||
|
||||
.. c:macro:: CAHUTE_PICTURE_FORMAT_1BIT_MONO
|
||||
|
||||
Constant representing the :ref:`picture-format-1bit`.
|
||||
|
||||
.. c:macro:: CAHUTE_PICTURE_FORMAT_1BIT_DUAL
|
||||
|
||||
Constant representing the :ref:`picture-format-2bit-dual`.
|
||||
|
||||
.. c:macro:: CAHUTE_PICTURE_FORMAT_4BIT_RGB_PACKED
|
||||
|
||||
Constant representing the :ref:`picture-format-4bit-rgb-packed`.
|
||||
|
||||
.. c:macro:: CAHUTE_PICTURE_FORMAT_16BIT_R5G6B5
|
||||
|
||||
Constant representing the :ref:`picture-format-r5g6b5`.
|
|
@ -0,0 +1,38 @@
|
|||
Cahute |version|
|
||||
================
|
||||
|
||||
.. warning::
|
||||
|
||||
Note that Cahute **is not released yet**, and such, tarballs have
|
||||
not been built yet, and the documentation and library structures
|
||||
is susceptible to change without warning.
|
||||
|
||||
**Please do not attempt to install Cahute until version 0.1 is released.**
|
||||
|
||||
Cahute is a library and set of command-line utilities to handle serial
|
||||
and USB communication protocols and file formats related to CASIO calculators,
|
||||
dating from the 1990s to today.
|
||||
|
||||
The project is also present `on Gitlab <Cahute on Gitlab_>`_.
|
||||
It is maintained by `Thomas Touhey`_.
|
||||
|
||||
The project's code and documentation contents are licensed under CeCILL_
|
||||
version 2.1 as distributed by the CEA, CNRS and Inria on
|
||||
`cecill.info <CeCILL_>`_.
|
||||
|
||||
This documentation is organized using `Diátaxis`_' structure.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
acknowledgements
|
||||
guides
|
||||
topics
|
||||
project
|
||||
cli
|
||||
headers
|
||||
|
||||
.. _Cahute on Gitlab: https://gitlab.com/cahuteproject/cahute
|
||||
.. _Thomas Touhey: https://thomas.touhey.fr/
|
||||
.. _CeCILL: http://www.cecill.info/licences.en.html
|
||||
.. _Diátaxis: https://diataxis.fr/
|
|
@ -0,0 +1,12 @@
|
|||
Project management
|
||||
==================
|
||||
|
||||
These documents describe the decisions taken for the project to handle
|
||||
collaboration efficiently.
|
||||
|
||||
.. toctree::
|
||||
|
||||
project/governance
|
||||
project/versioning
|
||||
project/contribution-style
|
||||
project/coding-style
|
|
@ -0,0 +1,111 @@
|
|||
.. _coding-style:
|
||||
|
||||
Coding style
|
||||
============
|
||||
|
||||
Cahute is made to be compatible with as much platforms as possible, adopting
|
||||
the lowest C standard (C89/C90) and protecting platform-specific usage
|
||||
behind macros as much as possible.
|
||||
|
||||
Formatting
|
||||
----------
|
||||
|
||||
In order to focus as much as possible on the work that matters, Cahute relies
|
||||
heavily on autoformatting and uncompromising sets of rules enforceable through
|
||||
tooling. This includes:
|
||||
|
||||
* For C code, the use the `clang-format`_ with a set of rules described in
|
||||
``.clang-format``, installed as a `pre-commit`_ hook.
|
||||
* For Python code, the use of Black_.
|
||||
|
||||
Otherwise, the rules are not yet clearly defined, and may be as a few
|
||||
contributions have gone by, and the standard for Cahute shapes itself a
|
||||
bit more clearly.
|
||||
|
||||
Namespace
|
||||
---------
|
||||
|
||||
Cahute reserves both the ``cahute_`` and ``CAHUTE_`` prefixes for all
|
||||
symbols and macros, i.e. it is recommended a library user does not use
|
||||
that prefix in any of their work.
|
||||
|
||||
Cahute respects reserved namespaces from C and POSIX; see
|
||||
`Open Group Base Specifications Issue 7, section 2.2.2 The Name Space`_
|
||||
for more information.
|
||||
|
||||
.. note::
|
||||
|
||||
This notably prevents us from using the ``_t`` suffix, since it
|
||||
is reserved by POSIX / Single UNIX Specification.
|
||||
|
||||
To avoid overlapping with user macros, **function and macro parameters are also
|
||||
defined within the Cahute namespaces**, more specifically in the ``cahute__``
|
||||
and ``CAHUTE__`` (*double underscore*) namespaces.
|
||||
|
||||
For example, a preprocessed Cahute macro and function declaration in public
|
||||
headers are the following::
|
||||
|
||||
#define CAHUTE_MY_MACRO(CAHUTE__ARG1, CAHUTE__ARG2) ...
|
||||
|
||||
int cahute_open_usb_link(
|
||||
cahute_link *cahute__linkp,
|
||||
unsigned long cahute__flags,
|
||||
int cahute__bus,
|
||||
int cahute__address
|
||||
);
|
||||
|
||||
.. note::
|
||||
|
||||
The namespace mainly applies to public headers from Cahute.
|
||||
Within internal headers and source files, **only exported symbols
|
||||
need to be placed within the reserved namespaces**.
|
||||
|
||||
Exported symbols in the Cahute static library can be found using ``nm``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
nm -CgU libcahute.a
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
Cahute is designed to be more compatible than not, but to make use of
|
||||
compiler and platform specific tools for static analysis if possible.
|
||||
As such, you must use the relevant compatibility macros for your case:
|
||||
|
||||
* Both function declarations and definitions must use the following:
|
||||
|
||||
- Either :c:macro:`CAHUTE_EXTERN`, or the function is only to be used by
|
||||
other code **in the same file**, :c:macro:`CAHUTE_LOCAL` or
|
||||
:c:macro:`CAHUTE_INLINE`.
|
||||
|
||||
Functions internal to Cahute but used cross-file must make use of
|
||||
:c:macro:`CAHUTE_EXTERN`, but be declared in ``lib/internals.h`` instead
|
||||
of the public headers.
|
||||
- :c:macro:`CAHUTE_NNPTR` and :c:macro:`CAHUTE_NONNULL` together, where
|
||||
relevant.
|
||||
* Function declarations only must use the following:
|
||||
|
||||
- :c:macro:`OF`\ ``((int arg1, char const *arg2, ...))`` for parameters.
|
||||
- :c:macro:`CAHUTE_DEPRECATED` and :c:macro:`CAHUTE_WUR` where relevant.
|
||||
|
||||
**Only utilities available in C89 / C90 must be used.**
|
||||
|
||||
For easier implementation, the following out-of-standard general utilities
|
||||
are available:
|
||||
|
||||
* Portable fixed-width integer types, in the form of :c:type:`cahute_u8`,
|
||||
:c:type:`cahute_u16` and :c:type:`cahute_u32`.
|
||||
* Portable printf specifiers for :c:type:`cahute_u8`, :c:type:`cahute_u16`,
|
||||
:c:type:`cahute_u32` and ``size_t``.
|
||||
* Endianness conversion utilities for both 16-bit and 32-bit integers,
|
||||
as :c:func:`cahute_be16toh`, :c:func:`cahute_le16toh`,
|
||||
:c:func:`cahute_be32toh`, :c:func:`cahute_le32toh`, :c:func:`cahute_htobe16`,
|
||||
:c:func:`cahute_htole16`, :c:func:`cahute_htobe32`, :c:func:`cahute_htole32`.
|
||||
|
||||
.. _pre-commit: https://pre-commit.com/
|
||||
.. _clang-format: https://clang.llvm.org/docs/ClangFormat.html
|
||||
.. _Black: https://github.com/psf/black
|
||||
.. _`Open Group Base Specifications Issue 7, section 2.2.2 The Name Space`:
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
|
||||
#tag_15_02_02
|
|
@ -0,0 +1,62 @@
|
|||
.. _contribution-style:
|
||||
|
||||
Contribution style
|
||||
==================
|
||||
|
||||
TL;DR:
|
||||
|
||||
* Contributors, especially external contributors, must work on a fork, and
|
||||
submit their work via a merge request.
|
||||
* Contributors can only target ``develop``, except maintainers that can
|
||||
target other release branches to backport fixes if need be.
|
||||
* Contributors must use `pre-commit`_ for autoformatting and linting their
|
||||
contribution.
|
||||
* Contributors must write documentation for their modifications on the
|
||||
library.
|
||||
|
||||
.. _project-commit-naming:
|
||||
|
||||
Commit naming
|
||||
-------------
|
||||
|
||||
Cahute uses `Conventional Commits`_, as enforced using Commitizen_ installed
|
||||
as a `pre-commit`_ hook.
|
||||
|
||||
Your commit messages must be in **imperative** form, i.e. ``do something``.
|
||||
|
||||
.. warning::
|
||||
|
||||
Please do **NOT** use past form, e.g. ``done something``.
|
||||
|
||||
.. note::
|
||||
|
||||
Scopes in commit messages aren't common in Cahute, but they can be
|
||||
accepted if they are relevant.
|
||||
|
||||
Coding style
|
||||
------------
|
||||
|
||||
The code included within the contribution must respect Cahute's coding
|
||||
style; see :ref:`coding-style` for more information.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Every modification on library code must be repercuted on the documentation.
|
||||
Think of it that way:
|
||||
|
||||
* If it is wrong in the code, it is most certainly wrong in the documentation.
|
||||
* If it is not present in the documentation, then it is missing, and must be
|
||||
added into it.
|
||||
* If it is added to the code, it must be added to the documentation.
|
||||
|
||||
Writing documentation is hard, and Diátaxis_' logic has to be learned in
|
||||
order to be applied efficiently. However, even bad documentation is
|
||||
documentation, and Cahute needs it to be sustainable, especially since
|
||||
Cahute implements reverse engineered protocols and file formats for which
|
||||
no official documentation exists!
|
||||
|
||||
.. _pre-commit: https://pre-commit.com/
|
||||
.. _Commitizen: https://commitizen-tools.github.io/commitizen/
|
||||
.. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0/
|
||||
.. _Diátaxis: https://diataxis.fr/
|
|
@ -0,0 +1,19 @@
|
|||
Project governance
|
||||
==================
|
||||
|
||||
`Thomas Touhey <https://thomas.touhey.fr/>`_ is the `Benevolent Dictator For
|
||||
Life`_ (BDFL) and only maintainer on this project, until a more sustainable
|
||||
solution is found and put into place or the project is made obsolete.
|
||||
|
||||
Contributions may be accepted by maintainers as long as they respect
|
||||
the :ref:`contribution-style`.
|
||||
|
||||
Issues may be addressed by maintainers or external contributors as long
|
||||
as they follow the issue reporting guide; see :ref:`issue-reporting-guide`.
|
||||
|
||||
Changes on the project management can only be made or accepted by the BDFL,
|
||||
unless a more sustainable model is found and put into place. Contributions
|
||||
making such changes can only be accepted by the BDFL.
|
||||
|
||||
.. _Benevolent Dictator For Life:
|
||||
https://en.wikipedia.org/wiki/Benevolent_dictator_for_life
|
|
@ -0,0 +1,79 @@
|
|||
Git and release versioning
|
||||
==========================
|
||||
|
||||
This document covers how the Git repository is organized, as well as how
|
||||
release numbers are organized.
|
||||
|
||||
Releases
|
||||
--------
|
||||
|
||||
Cahute's main source package distribution, also known as "tarballs", is
|
||||
on `ftp.cahuteproject.org/releases
|
||||
<https://ftp.cahuteproject.org/releases>`_.
|
||||
|
||||
Cahute uses `Semantic Versioning` with only major and minor versions, not
|
||||
patches. "Breaking changes" cover both the library and utilities, i.e.:
|
||||
|
||||
* If a valid usage of the library becomes invalid or produces an unexpected
|
||||
result (e.g. requests more privileges), breaking changes have occurred.
|
||||
* If a valid usage of any of the command-line utilities become invalid or
|
||||
produce an unexpected result, breaking changes have occurred.
|
||||
|
||||
Note however that **0.x versions don't require backwards compatible changes
|
||||
between minor versions**, only 1.0 and above, due to API incremental design
|
||||
and stabilization concerns.
|
||||
|
||||
.. _release-process:
|
||||
|
||||
Release process
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Only the BDFL can release a new version, by pushing a new commit
|
||||
``feat: release version x.y`` on ``develop`` that:
|
||||
|
||||
* Updates the project version in the ``project()`` function call in
|
||||
``CMakeLists.txt``.
|
||||
* Updates the project version with the ``version`` attribute of the
|
||||
``docs/conf.py`` file.
|
||||
|
||||
The BDFL then pushes a tag containing the version name, e.g. ``x.y`` in this
|
||||
case, and the CI, on detecting a new tag:
|
||||
|
||||
* Creates a tarball of the Git repository, and pushes it to the
|
||||
tarball distribution point with an associated SHA256 checksum file.
|
||||
* Builds the documentation and updates the main website using the newly
|
||||
generated files.
|
||||
|
||||
Git repository structure
|
||||
------------------------
|
||||
|
||||
Cahute's main repository is at `gitlab.com/cahuteproject/cahute
|
||||
<https://gitlab.com/cahuteproject/cahute>`_.
|
||||
**Only maintainers are allowed to push to it**; other contributors must work
|
||||
on a fork, then submit the remote branch as a merge request.
|
||||
|
||||
The main branch is ``develop``, which may have breaking changes at any point.
|
||||
At every release, a tag is created, pointing on the commit that has
|
||||
incremented the version; see :ref:`release-process` for more information.
|
||||
|
||||
If contributions, under the form of merge requests, are accepted, they are
|
||||
to be merged using fast-forward with no merge commit.
|
||||
|
||||
Maintainers are allowed to push their work on the repository under branches
|
||||
prefixed by one of the following:
|
||||
|
||||
* ``fix/``: If a fix is required for an issue, e.g.
|
||||
``fix/fix-bad-check-packet-type-on-special-mode``.
|
||||
* ``feat/``: For adding features such as adding a protocol, a file format,
|
||||
an option, and so on.
|
||||
* ``refactor/``: For refactoring part of the code or documentation.
|
||||
|
||||
Git commit messages must be named using the commit naming convention;
|
||||
see :ref:`project-commit-naming`.
|
||||
|
||||
.. note::
|
||||
|
||||
This structure, while simple, gives flexibility for release branches,
|
||||
hotfix branches, and so on, to be introduced later.
|
||||
|
||||
.. _Semantic Versioning: https://semver.org/
|
|
@ -0,0 +1,4 @@
|
|||
Sphinx~=7.2
|
||||
sphinx-autobuild
|
||||
sphinxcontrib-mermaid
|
||||
furo
|
|
@ -0,0 +1,14 @@
|
|||
Discussion topics
|
||||
=================
|
||||
|
||||
In this section, we will explore discussion topics regarding the project's
|
||||
environment and design. These topics provide keys to understanding what is
|
||||
happening in this project, and why it is happening.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
topics/picture-formats
|
||||
topics/protocols
|
||||
topics/usb-detection
|
||||
topics/logging
|
|
@ -0,0 +1,57 @@
|
|||
.. _logging:
|
||||
|
||||
Logging facilities with Cahute
|
||||
==============================
|
||||
|
||||
Cahute has logging facilities for its internal needs, which functions with
|
||||
logging levels.
|
||||
|
||||
Every log is accompanied with a level, among the following:
|
||||
|
||||
* ``info`` (:c:macro:`CAHUTE_LOGLEVEL_INFO`): debug messages, e.g. packet
|
||||
contents or activated behaviour tweaks that have been encountered.
|
||||
* ``warning`` (:c:macro:`CAHUTE_LOGLEVEL_WARNING`): messages signifying
|
||||
abnormal behaviours that are recoverable and recovered by the library.
|
||||
* ``error`` (:c:macro:`CAHUTE_LOGLEVEL_ERROR`): messages signifying abnormal
|
||||
behaviours that are not recoverable, and may cause link termination, or
|
||||
termination of a specific flow.
|
||||
* ``fatal`` (:c:macro:`CAHUTE_LOGLEVEL_FATAL`): messages signifying program
|
||||
termination, e.g. due to catastrophic system-related incidents.
|
||||
|
||||
Logging messages are printed on standard error if their level is allowed to
|
||||
be printed.
|
||||
|
||||
.. note::
|
||||
|
||||
There is no way currently to reroute these logs to another output than
|
||||
standard error. If the need arises, this may change.
|
||||
|
||||
Whether messages for a given logging level are printed or not can be
|
||||
controlled from the outside, by setting the current "logging level".
|
||||
Messages for a logging level can be printed if they are at the same or of
|
||||
higher importance than the currently configured logging level for the
|
||||
library, i.e. if they are on the same line or below in the list presented
|
||||
above.
|
||||
|
||||
By that rationale:
|
||||
|
||||
* If the currently configured logging level is ``info``, then messages will
|
||||
be displayed for all logging levels, since ``info`` has the lowest
|
||||
importance.
|
||||
* If the currently configured logging level is ``warning``, then messages
|
||||
will be displayed for the ``warning``, ``error`` and ``fatal`` logging
|
||||
level only.
|
||||
* If the currently configured logging level is ``error``, then messages
|
||||
will be displayed for the ``error`` and ``fatal`` logging levels only.
|
||||
* If the currently configured logging level is ``fatal``, then messages
|
||||
will be displayed for the ``fatal`` logging level only.
|
||||
|
||||
There is a special logging level ``none`` (:c:macro:`CAHUTE_LOGLEVEL_NONE`)
|
||||
that, if configured, will not let any log be printed.
|
||||
|
||||
As a library user, the current logging level can be gathered using
|
||||
:c:func:`cahute_get_log_level`, and can be set using
|
||||
:c:func:`cahute_set_log_level`.
|
||||
|
||||
As a command-line user, some command-line utilities support an ``-l`` and/or
|
||||
``--log`` option to set the current logging level for the library.
|
|
@ -0,0 +1,119 @@
|
|||
Picture formats
|
||||
===============
|
||||
|
||||
This document describes the various picture formats used by CASIO or other
|
||||
software surrounding its calculators in protocols and file formats.
|
||||
|
||||
.. _picture-format-1bit:
|
||||
|
||||
1bpp monochrome picture format
|
||||
------------------------------
|
||||
|
||||
This format is the basic frame format for fx-9860G calculators and compatible.
|
||||
It is used for internal VRAM representations, as well as for screenstreaming.
|
||||
|
||||
In this format, every pixel is represented as a bit, i.e. one byte contains
|
||||
8 pixels. An off bit (``0b0``) represents a white pixel, and an
|
||||
on bit (``0b1``) represents a black pixel.
|
||||
|
||||
The picture is organized by row first, column second.
|
||||
|
||||
If the width is not divisible by 8, then the last bits of the last
|
||||
byte of the row are unused (fill bits), and the next row starts at the
|
||||
beginning of the next byte.
|
||||
|
||||
For computing the size of such pictures, one must compute the number of bytes
|
||||
a row occupies (usually ``ceil(width / 8)``), then multiply it by the number
|
||||
of rows.
|
||||
|
||||
In Cahute, this format is represented by
|
||||
:c:macro:`CAHUTE_PICTURE_FORMAT_1BIT_MONO`.
|
||||
|
||||
.. _picture-format-2bit-dual:
|
||||
|
||||
Dual 1bpp gray picture format
|
||||
-----------------------------
|
||||
|
||||
This format is one of the possible screen streaming formats for fx-CG
|
||||
(Prizm) calculators, using the ``1RM2`` algorithm.
|
||||
|
||||
This format is basically two pictures using :ref:`picture-format-1bit`
|
||||
placed back-to-back (with alignment), where the obtained colours are
|
||||
the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Bit from picture 1/2
|
||||
- Bit from picture 2/2
|
||||
- Obtained colour (``0xRRGGBB``)
|
||||
* - ``0b0``
|
||||
- ``0b0``
|
||||
- ``0xFFFFFF``
|
||||
* - ``0b0``
|
||||
- ``0b1``
|
||||
- ``0xAAAAAA``
|
||||
* - ``0b1``
|
||||
- ``0b0``
|
||||
- ``0x777777``
|
||||
* - ``0b1``
|
||||
- ``0b1``
|
||||
- ``0x000000``
|
||||
|
||||
For computing the size of such pictures, one must compute the number of bytes
|
||||
a picture occupies, and multiply it by two, i.e. ``2 * ceil(width / 8)``.
|
||||
|
||||
In Cahute, this format is represented by
|
||||
:c:macro:`CAHUTE_PICTURE_FORMAT_1BIT_DUAL`.
|
||||
|
||||
.. _picture-format-4bit-rgb-packed:
|
||||
|
||||
4bpp packed RGB picture format
|
||||
------------------------------
|
||||
|
||||
This format is one of the possible screen streaming formats for fx-CG
|
||||
(Prizm) calculators, using the ``1RC3`` algorithm.
|
||||
|
||||
In this format, every pixel is represented by a nibble (group of
|
||||
4 consecutive bits), where, from high to low order:
|
||||
|
||||
- If the first bit is on (``0b1``), then the red component is set.
|
||||
- If the next bit is on (``0b1``), then the green component is set.
|
||||
- If the next bit is on (``0b1``), then the blue component is set.
|
||||
- The last bit is an alignment bit, and can be ignored.
|
||||
|
||||
The picture is organized by row first, column second.
|
||||
|
||||
If the width is not divisible by 2, then the last pixel of every odd row
|
||||
and the first pixel of every even row share the same byte, and if the height
|
||||
is also odd, then the last 4 bits of the picture will be present as alignment.
|
||||
|
||||
For computing the size of such pictures, one must compute the number of
|
||||
pixels, divide it by two and round to the next integer, i.e.
|
||||
``ceil(width * height / 2)``.
|
||||
|
||||
In Cahute, this format is represented by
|
||||
:c:macro:`CAHUTE_PICTURE_FORMAT_4BIT_RGB_PACKED`.
|
||||
|
||||
.. _picture-format-r5g6b5:
|
||||
|
||||
R5G6B5 picture format
|
||||
---------------------
|
||||
|
||||
This format is the basic frame format for fx-CG (Prizm) calculators.
|
||||
It is used for internal VRAM representations, as well as for screenstreaming
|
||||
using the ``1RC2`` algorithm.
|
||||
|
||||
In this format, every pixel is represented by a 16-bit integer represented
|
||||
using big endian, where, from high to low order:
|
||||
|
||||
- The first 5 bits represent the high 5 bits of the red component.
|
||||
- The next 6 bits represent the high 6 bits of the green component.
|
||||
- The last 5 bits represent the high 5 bits of the blue component.
|
||||
|
||||
The picture is organized by row first, column second.
|
||||
|
||||
The size of such pictures is the number of pixels multiplied by 2.
|
||||
|
||||
In Cahute, this format is represented by
|
||||
:c:macro:`CAHUTE_PICTURE_FORMAT_16BIT_R5G6B5`.
|
|
@ -0,0 +1,12 @@
|
|||
Communication protocols
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
protocols/cas40
|
||||
protocols/cas50
|
||||
protocols/cas100
|
||||
protocols/seven
|
||||
protocols/seven-ohp
|
||||
protocols/ums
|
|
@ -0,0 +1,10 @@
|
|||
.. _protocol-cas100:
|
||||
|
||||
CAS100 -- Serial protocol implemented by CASIO AFX calculators
|
||||
===============================================================
|
||||
|
||||
This protocol is used by AFX / Graph 100 calculators, produced in the
|
||||
early 2000s. It uses 50 bytes long headers at double the default speed
|
||||
from CAS50, 19200 bauds instead of 9600 bauds.
|
||||
|
||||
.. todo:: More information here.
|
|
@ -0,0 +1,14 @@
|
|||
.. _protocol-cas40:
|
||||
|
||||
CAS40 -- Serial protocol with 40 bytes long packets
|
||||
===================================================
|
||||
|
||||
This protocol is used on serial links with calculators from the early 1990s
|
||||
era.
|
||||
|
||||
.. todo:: More information here.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
cas40/packet-format
|
|
@ -0,0 +1,40 @@
|
|||
CAS40 packet format
|
||||
===================
|
||||
|
||||
The header format for a CAS40 packet is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 2 B
|
||||
- Type (*FT*)
|
||||
- File type.
|
||||
- See following sections.
|
||||
* - 2 (0x02)
|
||||
- 5 B
|
||||
- Type-specific data (*TD*).
|
||||
- Binary type-specific data.
|
||||
- ``\x00\x01\x00\x00\x00`` for a 0x100-long program.
|
||||
* - 7 (0x07)
|
||||
- 12 B
|
||||
- File name (*FN*)
|
||||
- Name of the file for an editor program.
|
||||
- ``HELLO\xFF\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 19 (0x13)
|
||||
- 12 B
|
||||
- File password (*FP*)
|
||||
- Password of the file for an editor program.
|
||||
- ``WORLD\xFF\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 31 (0x1F)
|
||||
- 7 B
|
||||
- Reserved
|
||||
- Should be set to ``\xFF``
|
||||
- ``\xFF\xFF\xFF\xFF\xFF...``
|
||||
|
||||
.. todo:: Describe file types here?
|
|
@ -0,0 +1,17 @@
|
|||
.. _protocol-cas50:
|
||||
|
||||
CAS50 -- Serial protocol with 50 bytes long packets
|
||||
===================================================
|
||||
|
||||
This protocol is used on serial links with calculators from the late 1990s
|
||||
era, and early 2000s era excluding AFX.
|
||||
|
||||
It is mostly used on serial links, with a default configuration of 9600 bauds,
|
||||
no parity and 1 stop bit.
|
||||
|
||||
.. todo:: More information here.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
cas50/packet-format
|
|
@ -0,0 +1,179 @@
|
|||
CAS50 packet format
|
||||
===================
|
||||
|
||||
All CAS50 packets are introduced by a single byte, which defines the basic
|
||||
purpose of the packet and the format and size of the payload following it.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Value
|
||||
- Name
|
||||
- Description
|
||||
- Payload
|
||||
* - ``0x06``
|
||||
- ``ACKNOWLEDGE``
|
||||
- The receiver accepts the data packet, confirms overwrite, or the
|
||||
sender confirms overwrite.
|
||||
- *(none)*
|
||||
* - ``0x13``
|
||||
- ``ESTABLISHED``
|
||||
- The receiver acknowledges connection establishment.
|
||||
- *(none)*
|
||||
* - ``0x15``
|
||||
- ``ABORT``
|
||||
- The sender requests an interactive connection, or aborts overwrite
|
||||
if an overwrite confirmation is requested.
|
||||
- *(none)*
|
||||
* - ``0x16``
|
||||
- ``START``
|
||||
- The sender requests a non-interactive connection.
|
||||
- *(none)*
|
||||
* - ``0x21``
|
||||
- ``ALREADY_EXISTS``
|
||||
- The receiver requests overwrite confirmation from the sender.
|
||||
- *(none)*
|
||||
* - ``0x24`` (or ``0x00``)
|
||||
- ``INVALID_DATA_TYPE``
|
||||
- The receiver rejects the data packet due to an invalid data type,
|
||||
or because it is out of memory.
|
||||
- *(none)*
|
||||
* - ``0x2b``
|
||||
- ``INVALID_CHECKSUM``
|
||||
- The received rejects the packet due to an invalid checksum.
|
||||
The transfer aborts.
|
||||
- *(none)*
|
||||
* - ``0x3a``
|
||||
- ``DATA``
|
||||
- Data payload.
|
||||
- :ref:`cas50-data-packets`
|
||||
* - ``0x51``
|
||||
- ``INVALID_DATA``
|
||||
- The receiver aborts the transfer due to errors in the header.
|
||||
- *(none)*
|
||||
|
||||
.. _cas50-data-packets:
|
||||
|
||||
Data packet payload
|
||||
-------------------
|
||||
|
||||
Data packet payloads, with the notable exception of the type (*T*) field which
|
||||
is specific to the protocol, mirror the internal format in the calculator's
|
||||
main memory, including the header.
|
||||
|
||||
The format of the payload header is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 4 B
|
||||
- Type (*T*)
|
||||
- Basic purpose of the packet
|
||||
- ``END\0``
|
||||
* - 2 (0x02)
|
||||
- 2 B
|
||||
- File Type (*FT*)
|
||||
- File type, used by ``TXT`` packets.
|
||||
- ``PG``
|
||||
* - 4 (0x04)
|
||||
- 4 B
|
||||
- File Size (*FS*)
|
||||
- Size of the data accompanying the header (big endian).
|
||||
- ``\x00\x00\x00\xFF``
|
||||
* - 8 (0x08)
|
||||
- 8 B
|
||||
- File Name (*FN*)
|
||||
- Name of the file, with unset bytes being set to ``\xFF``.
|
||||
- ``HELLO\xFF\xFF\xFF``
|
||||
* - 16 (0x10)
|
||||
- 8 B
|
||||
- Alternative File Type (*AFT*)
|
||||
- Alternative file type used for some packet types, notably variables.
|
||||
- ``VariableR\x0A``
|
||||
* - 24 (0x18)
|
||||
- 8 B
|
||||
- File Password (*FP*)
|
||||
- Password of the file, with unset bytes being set to ``\xFF``.
|
||||
- ``WORLD\xFF\xFF\xFF``
|
||||
* - 32 (0x20)
|
||||
- 2 B
|
||||
- Base, if the file is a program.
|
||||
- ``BN`` for Base programs, ``NL`` otherwise.
|
||||
- ``BN``
|
||||
* - 34 (0x22)
|
||||
- 6 B
|
||||
- Backup Size (*BS*) *(?)*
|
||||
- Size of the backup (big endian).
|
||||
- ``\x00\x10\x00\x00\x00\x00``
|
||||
* - 40 (0x28)
|
||||
- 6 B
|
||||
- (unknown)
|
||||
- Unknown, filled with ``\xFF``.
|
||||
- ``\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 48 (0x30)
|
||||
- 2 B
|
||||
- Checksum (*CS*)
|
||||
- Checksum (big endian).
|
||||
- ``\x12\x34``
|
||||
|
||||
Note that any field not used by the packet type should be set to ``\xFF``.
|
||||
|
||||
``END\xFF`` packets
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. todo:: Describe the packet's role.
|
||||
|
||||
All fields other than the type aren't used, and should be set to ``\xFF``.
|
||||
|
||||
``TXT\0`` packets
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets carry over a main memory textual file.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Subtype (*ST*) value
|
||||
- Description
|
||||
* - ``PG``
|
||||
- Program.
|
||||
|
||||
``IMG\0`` packets
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets carry over a main memory picture file.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Subtype (*ST*) value
|
||||
- Description
|
||||
* - ``PC``
|
||||
- Picture.
|
||||
|
||||
``MEM\0`` packets
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets carry over a backup.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Subtype (*ST*) value
|
||||
- Description
|
||||
* - ``BU``
|
||||
- Backup.
|
||||
|
||||
``VAL\0`` packets
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets carry over a variable. Particularities for this packet are:
|
||||
|
||||
* *FN* should be set to the variable name (?).
|
||||
* *AFT* should be set to ``VariableR\x0A``.
|
|
@ -0,0 +1,31 @@
|
|||
.. _protocol-seven-ohp:
|
||||
|
||||
Protocol 7.00 Screenstreaming -- fx-9860G and fx-CG screenstreaming
|
||||
===================================================================
|
||||
|
||||
Screenstreaming, also named "OverHead Projector" (OHP), "Projector", or
|
||||
"Screen Receiver"\ [#screenreceiver]_, is a mode in which the calculator
|
||||
shares its screen contents to another device.
|
||||
|
||||
This protocol is analogous to Protocol 7.00, see :ref:`protocol-seven` for
|
||||
more information. It is used on the same models and during the same period
|
||||
of time.
|
||||
|
||||
However, it has its own packet formats and flows that make it effectively
|
||||
a completely separate protocol, sharing only a few similarities. Therefore,
|
||||
it is documented in a completely separated set of sections and documents
|
||||
from the original protocol, for clarity.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
seven-ohp/packet-format
|
||||
seven-ohp/flows
|
||||
|
||||
.. [#screenreceiver] `Screen Receiver`_ is the name of the piece of software
|
||||
by CASIO to view the calculator's screen from a desktop PC running on
|
||||
MacOS, OS X or Microsoft Windows.
|
||||
|
||||
.. _Screen Receiver:
|
||||
https://www.planet-casio.com/Fr/logiciels/voir_un_logiciel_casio.php
|
||||
?showid=102
|
|
@ -0,0 +1,57 @@
|
|||
Protocol 7.00 Screenstreaming communication flows
|
||||
=================================================
|
||||
|
||||
Screenstreaming with Protocol 7.00 involves a **sender** and a **receiver**.
|
||||
The objective with this protocol is for the sender to be able to
|
||||
send frames as they are produced to the receiver.
|
||||
|
||||
Except for a conditional acknowledgement at the beginning of the flow,
|
||||
the receiver does not send anything, and **in case of invalid checksum,
|
||||
it discards such packets**.
|
||||
|
||||
The communication schema is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant sender as Sender<br />(Calculator)
|
||||
Participant receiver as Receiver<br />(PC, ...)
|
||||
|
||||
alt Sender requires acknowledgement from the Receiver
|
||||
sender->>receiver: Check packet
|
||||
receiver->>sender: Acknowledgement packet
|
||||
end
|
||||
|
||||
loop Screenstreaming is active
|
||||
sender->>receiver: Frame packet
|
||||
end
|
||||
|
||||
.. warning::
|
||||
|
||||
Sometimes, due to the high volume of data, a few bytes can be skipped
|
||||
here and there, leading to a desynchronization on the input stream.
|
||||
It is recommended, on the receiving function, to add an option to
|
||||
find the beginning of the next screenstreaming packet, to fix such
|
||||
desynchronized inputs.
|
||||
|
||||
.. _seven-ohp-acknowledge:
|
||||
|
||||
Acknowledge a Sender
|
||||
--------------------
|
||||
|
||||
On certain conditions, such as when the ``ScreenRecv(XP)`` mode is used on
|
||||
the fx-CG50, the sender requires acknowledgement from the receiver.
|
||||
As such, it will continuously send check packets, such as the following one::
|
||||
|
||||
16 43 41 4c 30 30 44 30 .CAL00D0
|
||||
|
||||
In such cases, the receiver must answer with the following acknowledgement
|
||||
packet::
|
||||
|
||||
06 30 32 30 30 31 30 44 .020010D
|
||||
|
||||
Once the sender has received acknowledgement, it will start sending
|
||||
frame packets.
|
||||
|
||||
For more information, see :ref:`seven-ohp-check-packet` and
|
||||
:ref:`seven-ohp-ack-packet`.
|
|
@ -0,0 +1,227 @@
|
|||
Protocol 7.00 Screenstreaming packet format
|
||||
===========================================
|
||||
|
||||
This document defines the packet formats for Protocol 7.00 Screenstreaming.
|
||||
|
||||
.. note::
|
||||
|
||||
In places, most notably in some subheaders and with the checksum, the
|
||||
protocol uses the same ASCII-HEX encoding as for Protocol 7.00;
|
||||
see :ref:`seven-ascii-hex` for more information.
|
||||
|
||||
Fields represented using ASCII-HEX will reference the section from
|
||||
Protocol 7.00 packet format directly.
|
||||
|
||||
All packets with Protocol 7.00 Screenstreaming packet have the
|
||||
|
||||
The packet mode for this mode is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 1 B
|
||||
- Type (*T*)
|
||||
- Basic purpose of the packet
|
||||
- 0x00 to 0x1F
|
||||
* - 1 (0x01)
|
||||
- 5 B
|
||||
- Subtype (*ST*)
|
||||
- Subtype for the packet.
|
||||
- 5-char ASCII string depending on the type.
|
||||
* - 6 (0x06)
|
||||
- *N* B
|
||||
- Payload (*D*)
|
||||
- Payload, for which the format depends on the format.
|
||||
-
|
||||
* - 6 + *N* (0x06 + *N*)
|
||||
- 2 B
|
||||
- Checksum (*CS*)
|
||||
- Checksum for the packet.
|
||||
- 2-char :ref:`seven-ascii-hex` value, e.g. ``5B``.
|
||||
|
||||
The checksum is computed :ref:`the same way as for Protocol 7.00
|
||||
<seven-checksum>`, that is to say, it is obtained by summing all bytes from
|
||||
*ST* to *D* included (i.e. the entire packet except *T* and *CS*), and
|
||||
adding 1 to its bitwise complement.
|
||||
|
||||
The interpretation of the packet depends on the value of *T*.
|
||||
See the following sections for more information.
|
||||
|
||||
.. note::
|
||||
|
||||
The header does not specify the total size of the packet, which implies
|
||||
that it must be computed using the type, subtype and eventual subheader.
|
||||
This, unfortunately, makes it more susceptible to corruption.
|
||||
|
||||
.. _seven-ohp-ack-packet:
|
||||
|
||||
``0x06`` -- Acknowledgement packet
|
||||
----------------------------------
|
||||
|
||||
The acknowledgement packet can be used to accept a synchronization, so that
|
||||
the sender starts sending frame packets instead of check packets. See
|
||||
:ref:`seven-ohp-acknowledge` for more information.
|
||||
|
||||
The only known subtype of this packet is ``02001``.
|
||||
|
||||
.. _seven-ohp-frame-packet:
|
||||
|
||||
``0x0B`` -- Frame packet
|
||||
------------------------
|
||||
|
||||
The frame packet contains a frame of the screen.
|
||||
|
||||
``TYP01`` frame format
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets are sent by the fx-9860G and compatible on screenstreaming
|
||||
mode, and are of the following format:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 6 (0x06)
|
||||
- 1024 B
|
||||
- Frame (*F*)
|
||||
- Frame data, as a 128x64 1-bit monochrome picture; see
|
||||
:ref:`picture-format-1bit` for more information.
|
||||
-
|
||||
|
||||
.. _seven-screen-typz1:
|
||||
|
||||
``TYPZ1`` frame format
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets are sent by the fx-CG series on screenstreaming modes, and are
|
||||
of the following format:
|
||||
|
||||
.. warning::
|
||||
|
||||
In this table, the offset starts at 6 instead of 0.
|
||||
The subheader itself is only 18 bytes long!
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 6 (0x06)
|
||||
- 6 B
|
||||
- Frame Length (*FL*)
|
||||
- Length of the *F* field.
|
||||
- 6-char :ref:`seven-ascii-hex` value, e.g. ``001234``.
|
||||
* - 12 (0x0C)
|
||||
- 4 B
|
||||
- Height (*H*)
|
||||
- Height of the frame, in pixels.
|
||||
- 4-char :ref:`seven-ascii-hex` value, e.g. ``0123``.
|
||||
* - 16 (0x10)
|
||||
- 4 B
|
||||
- Width (*W*)
|
||||
- Width of the frame, in pixels.
|
||||
- 4-char :ref:`seven-ascii-hex` value, e.g. ``0123``.
|
||||
* - 20 (0x14)
|
||||
- 4B
|
||||
- Frame Format (*FF*)
|
||||
- Format of the frame, i.e. picture encoding in use.
|
||||
- ``1RC2``, ``1RC3``, ``1RM2``
|
||||
* - 24 (0x18)
|
||||
- *FL* B
|
||||
- Frame (*F*)
|
||||
- Frame data.
|
||||
-
|
||||
|
||||
The frame formats are the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - *FF* field value
|
||||
- Format
|
||||
- Expected size
|
||||
* - ``1RC2``
|
||||
- :ref:`picture-format-r5g6b5`
|
||||
- ``width * height * 2``
|
||||
* - ``1RC3``
|
||||
- :ref:`picture-format-4bit-rgb-packed`
|
||||
- ``ceil(width * height / 2)``
|
||||
* - ``1RM2``
|
||||
- :ref:`picture-format-2bit-dual`
|
||||
- ``2 * height * ceil(width / 8)``
|
||||
|
||||
``TYPZ2`` frame format
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Such packets can also be sent by the fx-CG series on screenstreaming modes,
|
||||
and are of the following format:
|
||||
|
||||
.. warning::
|
||||
|
||||
In this table, the offset starts at 6 instead of 0.
|
||||
The subheader itself is only 20 bytes long!
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 6 (0x06)
|
||||
- 8 B
|
||||
- Frame Length (*FL*)
|
||||
- Length of the *F* field.
|
||||
- 8-char :ref:`seven-ascii-hex` value, e.g. ``00001234``.
|
||||
* - 14 (0x0E)
|
||||
- 4 B
|
||||
- Height (*H*)
|
||||
- Height of the frame, in pixels.
|
||||
- 4-char :ref:`seven-ascii-hex` value, e.g. ``0123``.
|
||||
* - 18 (0x12)
|
||||
- 4 B
|
||||
- Width (*W*)
|
||||
- Width of the frame, in pixels.
|
||||
- 4-char :ref:`seven-ascii-hex` value, e.g. ``0123``.
|
||||
* - 22 (0x16)
|
||||
- 4B
|
||||
- Frame Format (*FF*)
|
||||
- Format of the frame, i.e. picture encoding in use.
|
||||
- ``1RC2``, ``1RC3``, ``1RM2``
|
||||
* - 26 (0x1A)
|
||||
- *FL* B
|
||||
- Frame (*F*)
|
||||
- Frame data.
|
||||
-
|
||||
|
||||
.. note::
|
||||
|
||||
This is roughly equivalent to the :ref:`seven-screen-typz1`, with
|
||||
the *FL* field having been changed from 6 to 8 chars to allow
|
||||
larger frames.
|
||||
|
||||
The frame formats are the same as for :ref:`seven-screen-typz1`.
|
||||
|
||||
.. _seven-ohp-check-packet:
|
||||
|
||||
``0x16`` -- Check packet
|
||||
------------------------
|
||||
|
||||
Check packets are sent by the sender to request an acknowledgement from the
|
||||
receiver. See :ref:`seven-ohp-acknowledge` for more information.
|
||||
|
||||
The only known subtype for this mode is ``CAL00``.
|
|
@ -0,0 +1,23 @@
|
|||
.. _protocol-seven:
|
||||
|
||||
Protocol 7.00 -- Serial and USB protocol used by post fx-9860G calculators
|
||||
==========================================================================
|
||||
|
||||
This protocol is used by calculators starting from the fx-9860G, published
|
||||
in 2004, up to the current day.
|
||||
|
||||
.. note::
|
||||
|
||||
fx-CG calculators and derivatives still use a derivative from Protocol
|
||||
7.00, although not directly, but hidden behind proprietary SCSI commands.
|
||||
See :ref:`protocol-ums` for more information.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
seven/specific-encodings
|
||||
seven/packet-format
|
||||
seven/flows
|
||||
seven/casio-commands
|
||||
seven/use-cases
|
||||
seven/hardware-identifiers
|
|
@ -0,0 +1,756 @@
|
|||
Known Protocol 7.00 commands by CASIO
|
||||
=====================================
|
||||
|
||||
These commands have been defined by CASIO through their Protocol 7.00
|
||||
implementations. Some may no longer be implemented on newer models.
|
||||
|
||||
.. _seven-command-00:
|
||||
|
||||
``00`` "Restart"
|
||||
----------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 00
|
||||
|
||||
Restart or reset the device.
|
||||
|
||||
.. _seven-command-01:
|
||||
|
||||
``01`` "Get device information"
|
||||
-------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 01
|
||||
|
||||
Request an extended ACK with subtype ``02``, and a payload containing
|
||||
device information.
|
||||
|
||||
See :ref:`seven-get-device-information` for the related flow, and
|
||||
:ref:`seven-ack-packet` for more information regarding the payload format.
|
||||
|
||||
.. _seven-command-02:
|
||||
|
||||
``02`` "Set link settings"
|
||||
--------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 02
|
||||
:d1: Baud rate in decimal format.
|
||||
:d1-example: 19200
|
||||
:d2: Parity, among "ODD", "EVEN" or "NONE".
|
||||
:d2-example: EVEN
|
||||
:d3: Stop bits, "1" or "2".
|
||||
:d3-example: 2
|
||||
|
||||
If connected to the passive device using a serial link, this command
|
||||
signifies a request to communicate using different serial parameters.
|
||||
|
||||
.. note::
|
||||
|
||||
The serial speeds are limited to the following speeds (or baud rates):
|
||||
300, 600, 1200, 2400, 4800, 9600 (*by default*), 19200, 38400, 57600
|
||||
and 115200 bauds.
|
||||
|
||||
See :ref:`seven-update-serial-params` for more information.
|
||||
|
||||
.. _seven-command-06:
|
||||
|
||||
``06`` "Set link timeout"
|
||||
-------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 06
|
||||
:d1: 4-char :ref:`seven-ascii-hex` number of minutes
|
||||
:d1-example: 0001
|
||||
|
||||
Set the timeout for the link, after which the connection is terminated.
|
||||
|
||||
.. todo:: Does the calculator send a termination packet?
|
||||
|
||||
.. _seven-command-07:
|
||||
|
||||
``07`` Verification 1 (OS Update)
|
||||
---------------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-08:
|
||||
|
||||
``08`` Verification 2 (OS Update)
|
||||
---------------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-09:
|
||||
|
||||
``09`` Verification 3 (OS Update)
|
||||
---------------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-0A:
|
||||
|
||||
``0A`` Verification 4 (OS Update)
|
||||
---------------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-20:
|
||||
|
||||
``20`` "Create directory" (main memory)
|
||||
---------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 20
|
||||
:d1: Name of the directory to create.
|
||||
:d1-example: HELLO
|
||||
|
||||
Create a directory on the main memory root.
|
||||
|
||||
.. _seven-command-21:
|
||||
|
||||
``21`` "Delete directory" (main memory)
|
||||
---------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 21
|
||||
:d1: Name of the directory to delete.
|
||||
:d1-example: HELLO
|
||||
|
||||
Delete a directory on the main memory root.
|
||||
|
||||
.. _seven-command-22:
|
||||
|
||||
``22`` "Rename directory" (main memory)
|
||||
---------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 22
|
||||
:d1: Name of the directory to rename.
|
||||
:d1-example: HELLO
|
||||
:d2: New name for the directory.
|
||||
:d2-example: WORLD
|
||||
|
||||
Rename a directory on the main memory root.
|
||||
|
||||
.. _seven-command-23:
|
||||
|
||||
``23`` "Change working directory" (main memory)
|
||||
-----------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 23
|
||||
:d1: Name of the directory (or "" for root).
|
||||
:d1-example: HELLO
|
||||
|
||||
Change the working directory on the main memory.
|
||||
|
||||
.. note::
|
||||
|
||||
When provided and not empty, the directory name is always from the
|
||||
root, since the main memory doesn't support more depth.
|
||||
|
||||
.. _seven-command-24:
|
||||
|
||||
``24`` "Request file transfer" (main memory)
|
||||
--------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 24
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLSOUMOI
|
||||
:d3: Group name.
|
||||
|
||||
Request a main memory file to be transferred, using command
|
||||
:ref:`seven-command-25`.
|
||||
|
||||
.. _seven-command-25:
|
||||
|
||||
``25`` "Transfer file" (main memory)
|
||||
------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 25
|
||||
:ow: Overwrite mode.
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:fs: File size.
|
||||
:fs-example: 00012345
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLSOUMOI
|
||||
:d3: Group name.
|
||||
|
||||
Transfer a main memory file.
|
||||
|
||||
.. _seven-command-26:
|
||||
|
||||
``26`` "Delete file" (main memory)
|
||||
----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 26
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:fs: File size.
|
||||
:fs-example: 00012345
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLSOUMOI
|
||||
:d3: Group name.
|
||||
|
||||
Delete a main memory file.
|
||||
|
||||
.. _seven-command-27:
|
||||
|
||||
``27`` "Rename file" (main memory)
|
||||
----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 27
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLSOUMOI
|
||||
:d3: New file name.
|
||||
:d3-example: PLUSMOIN
|
||||
|
||||
Rename a main memory file.
|
||||
|
||||
.. _seven-command-28:
|
||||
|
||||
``28`` "Copy file" (main memory)
|
||||
--------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 28
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLUSMOIN
|
||||
:d3: New directory name.
|
||||
:d3-example: system
|
||||
:d4: New file name.
|
||||
:d4-example: PLMNCOPY
|
||||
|
||||
Copy a main memory file into another on the device.
|
||||
|
||||
.. _seven-command-29:
|
||||
|
||||
``29`` "Request transfer of all files" (main memory)
|
||||
----------------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 29
|
||||
|
||||
Request all main memory files to be transferred using command
|
||||
:ref:`seven-command-25`.
|
||||
|
||||
.. _seven-command-2A:
|
||||
|
||||
``2A`` "Reset" (main memory)
|
||||
----------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2A
|
||||
|
||||
Reset main memory.
|
||||
|
||||
.. _seven-command-2B:
|
||||
|
||||
``2B`` "Request available capacity" (main memory)
|
||||
-------------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2B
|
||||
|
||||
Request the available capacity on the main memory to be transferred
|
||||
using command :ref:`seven-command-2C`.
|
||||
|
||||
.. _seven-command-2C:
|
||||
|
||||
``2C`` "Transfer available capacity" (main memory)
|
||||
--------------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2C
|
||||
:fs: Available capacity.
|
||||
:fs-example: 00123456
|
||||
|
||||
Transfer the available capacity on the main memory.
|
||||
|
||||
.. _seven-command-2D:
|
||||
|
||||
``2D`` "Request all file information" (main memory)
|
||||
---------------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2D
|
||||
|
||||
Transfer information regarding all main memory files, using
|
||||
command :ref:`seven-command-2E`.
|
||||
|
||||
.. _seven-command-2E:
|
||||
|
||||
``2E`` "Transfer file information" (main memory)
|
||||
------------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2E
|
||||
:dt: Main memory data type.
|
||||
:dt-example: 01
|
||||
:fs: File size.
|
||||
:fs-example: 00012345
|
||||
:d1: Directory name.
|
||||
:d1-example: system
|
||||
:d2: File name.
|
||||
:d2-example: PLUSMOIN
|
||||
:d3: Group name.
|
||||
|
||||
Transfer information regarding a main memory file.
|
||||
|
||||
.. _seven-command-2F:
|
||||
|
||||
``2F`` "Request raw main memory"
|
||||
--------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 2F
|
||||
|
||||
Request the raw main memory to be sent using command
|
||||
:ref:`seven-command-30`.
|
||||
|
||||
.. _seven-command-30:
|
||||
|
||||
``30`` "Transfer raw main memory"
|
||||
---------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 30
|
||||
|
||||
Transfer the raw main memory.
|
||||
|
||||
.. _seven-command-31:
|
||||
|
||||
``31`` "Request setup entry"
|
||||
----------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 31
|
||||
:d1: Setup entry name.
|
||||
|
||||
Request a setup entry, to be sent using command :ref:`seven-command-32`.
|
||||
|
||||
.. _seven-command-32:
|
||||
|
||||
``32`` "Transfer setup entry"
|
||||
-----------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 32
|
||||
:d1: Setup entry name.
|
||||
:d1-example: Angle
|
||||
:d2: Setup entry value.
|
||||
:d2-example: 01
|
||||
|
||||
Send a setup entry.
|
||||
|
||||
.. _seven-command-33:
|
||||
|
||||
``33`` "Request all setup entries"
|
||||
----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 33
|
||||
|
||||
Request all setup entries to be sent using command
|
||||
:ref:`seven-command-32`.
|
||||
|
||||
.. _seven-command-40:
|
||||
|
||||
``40`` "Create directory" (storage)
|
||||
-----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 40
|
||||
:d1: Directory name.
|
||||
:d1-example: MYFOLDER
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Create a directory on the provided storage device.
|
||||
|
||||
.. _seven-command-41:
|
||||
|
||||
``41`` "Delete directory" (storage)
|
||||
-----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 41
|
||||
:d1: Directory name.
|
||||
:d1-example: MYFOLDER
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Delete a directory on the provided storage device.
|
||||
|
||||
.. _seven-command-42:
|
||||
|
||||
``42`` "Rename directory" (storage)
|
||||
-----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 42
|
||||
:d1: Directory name.
|
||||
:d1-example: MYFOLDER
|
||||
:d2: New directory name.
|
||||
:d2-example: PRECIOUS
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Rename a directory on the provided storage device.
|
||||
|
||||
.. _seven-command-43:
|
||||
|
||||
``43`` "Change working directory" (storage)
|
||||
-------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 43
|
||||
:d1: Directory name.
|
||||
:d1-example: MYFOLDER
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Update the working directory on the given device.
|
||||
|
||||
.. _seven-command-44:
|
||||
|
||||
``44`` "Request file" (storage)
|
||||
-------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 44
|
||||
:d1: Directory name.
|
||||
:d1-example: MYFOLDER
|
||||
:d2: File name.
|
||||
:d2-example: MYADDIN.G1A
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Request for a file to be sent on the given device.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-request-file-from-storage`.
|
||||
|
||||
.. _seven-command-45:
|
||||
|
||||
``45`` "Transfer file" (storage)
|
||||
--------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 45
|
||||
:ow: Overwrite mode.
|
||||
:ow-example: 02
|
||||
:fs: File size.
|
||||
:fs-example: 00123456
|
||||
:d1: Directory name.
|
||||
:d2: File name.
|
||||
:d2-example: MYADDIN.G1A
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Transfer a file to be sent on the given device.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-send-file-to-storage`;
|
||||
* :ref:`seven-request-file-from-storage`.
|
||||
|
||||
.. _seven-command-46:
|
||||
|
||||
``46`` "Delete file" (storage)
|
||||
------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 46
|
||||
:d1: Directory name.
|
||||
:d2: File name.
|
||||
:d2-example: MYADDIN.G1A
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Delete a file on the given device.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-delete-file-on-storage`.
|
||||
|
||||
.. _seven-command-47:
|
||||
|
||||
``47`` "Rename file" (storage)
|
||||
------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 47
|
||||
:d1: Directory name.
|
||||
:d2: File name.
|
||||
:d2-example: MYADDIN.G1A
|
||||
:d3: New file name.
|
||||
:d3-example: GRAVDUCK.G1A
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Rename a file on the given device.
|
||||
|
||||
.. _seven-command-48:
|
||||
|
||||
``48`` "Copy file" (storage)
|
||||
----------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 48
|
||||
:d1: Directory name.
|
||||
:d2: File name.
|
||||
:d2-example: ORIGNAME.G1A
|
||||
:d3: New directory name.
|
||||
:d4: New file name.
|
||||
:d4-example: NEWNAME.G1A
|
||||
:d5: Device name.
|
||||
:d5-example: fls0
|
||||
|
||||
Copy a file on the given device.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-copy-file-on-storage`.
|
||||
|
||||
.. _seven-command-49:
|
||||
|
||||
``49`` "Request all files" (storage)
|
||||
------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 49
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Request all files to be transmitted using command
|
||||
:ref:`seven-command-45`.
|
||||
|
||||
.. _seven-command-4A:
|
||||
|
||||
``4A`` "Reset" (storage)
|
||||
------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 4A
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Reset a storage device.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-reset-storage`.
|
||||
|
||||
.. _seven-command-4B:
|
||||
|
||||
``4B`` "Request available capacity" (storage)
|
||||
---------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 4B
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Request the available capacity for a given storage device.
|
||||
|
||||
.. _seven-command-4C:
|
||||
|
||||
``4C`` "Transfer available capacity" (storage)
|
||||
----------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 4C
|
||||
:fs: Available capacity
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Provide the available capacity for a given storage device.
|
||||
|
||||
.. _seven-command-4D:
|
||||
|
||||
``4D`` "Request all file information" (storage)
|
||||
-----------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 4D
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Request information from all files on the given storage device
|
||||
to be transferred.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-list-files-on-storage`.
|
||||
|
||||
.. _seven-command-4E:
|
||||
|
||||
``4E`` "Transfer file information" (storage)
|
||||
--------------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 4E
|
||||
:fs: File size
|
||||
:d1: Directory name
|
||||
:d2: File name
|
||||
:d2-example: MYADDIN.G1A
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Transfer information regarding a file.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-list-files-on-storage`.
|
||||
|
||||
.. _seven-command-4F:
|
||||
|
||||
``4F`` "Request flash image"
|
||||
----------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-50:
|
||||
|
||||
``50`` "Transfer flash image"
|
||||
-----------------------------
|
||||
|
||||
.. todo:: Describe this command.
|
||||
|
||||
.. _seven-command-51:
|
||||
|
||||
``51`` "Optimize filesystem" (storage)
|
||||
--------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 51
|
||||
:d5: Storage device
|
||||
:d5-example: fls0
|
||||
|
||||
Transfer information regarding a file.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-optimize-storage`.
|
||||
|
||||
.. _seven-command-52:
|
||||
|
||||
``52`` "Request CASIOWIN entry transfer"
|
||||
----------------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 52
|
||||
|
||||
Request the CASIOWIN entry to be transferred using command
|
||||
:ref:`seven-command-53`.
|
||||
|
||||
.. _seven-command-53:
|
||||
|
||||
``53`` "Transfer CASIOWIN entry"
|
||||
--------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 53
|
||||
|
||||
Transfer the CASIOWIN entry.
|
||||
|
||||
.. _seven-command-54:
|
||||
|
||||
``54`` "Request bootcode transfer"
|
||||
----------------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 54
|
||||
|
||||
Request the bootcode to be transferred using command
|
||||
:ref:`seven-command-55`.
|
||||
|
||||
.. _seven-command-55:
|
||||
|
||||
``55`` "Transfer bootcode"
|
||||
--------------------------
|
||||
|
||||
.. seven-command::
|
||||
:code: 55
|
||||
|
||||
Transfer the bootcode.
|
||||
|
||||
.. _seven-command-56:
|
||||
|
||||
``56`` "Upload and run"
|
||||
-----------------------
|
||||
|
||||
Upload and run a specially crafted program.
|
||||
|
||||
.. warning::
|
||||
|
||||
Please do not use this command lightly, as uploading badly formatted
|
||||
programs or the incorrect program for your calculator **can brick said
|
||||
calculator**!
|
||||
|
||||
This command does not use the typical command payload, but a **custom 24-bytes
|
||||
payload** for which the format is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 8 B
|
||||
- Upload size
|
||||
- Size of the payload to upload.
|
||||
- 8-char :ref:`seven-ascii-hex` number.
|
||||
* - 8 (0x08)
|
||||
- 8 B
|
||||
- Load address
|
||||
- RAM address at which to load the provided payload.
|
||||
- 8-char :ref:`seven-ascii-hex` number, usually set to
|
||||
``88030000``.
|
||||
* - 16 (0x10)
|
||||
- 8 B
|
||||
- Start address
|
||||
- Address which to jump to after successful upload.
|
||||
- 8-char :ref:`seven-ascii-hex` number, usually set to
|
||||
``88030000``.
|
||||
|
||||
This command is used in the following use cases:
|
||||
|
||||
* :ref:`seven-upload-and-run`.
|
||||
|
||||
``59`` "Backup main memory" (fx-CG)
|
||||
-----------------------------------
|
||||
|
||||
.. todo:: Describe this command, known as "save Backup.g3m".
|
||||
|
||||
``5A`` "Restore main memory" (fx-CG)
|
||||
------------------------------------
|
||||
|
||||
.. todo:: Describe this command, known as "restore Backup.g3m".
|
|
@ -0,0 +1,380 @@
|
|||
Protocol 7.00 communication flows
|
||||
=================================
|
||||
|
||||
Protocol 7.00 involves an **active side** and a **passive side**.
|
||||
At the beginning of the communication, the passive side is usually the
|
||||
calculator, and the active side is the client, e.g. a PC or another
|
||||
calculator.
|
||||
|
||||
When a flow isn't currently in progress, the active side is allowed to send
|
||||
a command to the passive side. This command may start a flow where a
|
||||
"role swap" occurs, i.e. the active side becomes the passive side, and vice
|
||||
versa. At the end of said flow, the role are usually swapped again, so that
|
||||
the original active side becomes the active side again.
|
||||
|
||||
When required, the role swap is always initiated by the active side.
|
||||
|
||||
The communication schema is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Original Active Side<br>(PC, ...)
|
||||
Participant passive as Original Passive Side<br>(calculator)
|
||||
|
||||
Note over active,passive: Initialize the link
|
||||
|
||||
active->>passive: Command
|
||||
alt Erroneous
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: ACK
|
||||
|
||||
alt Data transfer is required
|
||||
Note over active,passive: Data transfer
|
||||
else
|
||||
alt Data transfer must be requested by the active side
|
||||
Note over active,passive: Data transfer request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Note over active,passive: Terminate the link
|
||||
|
||||
The different blocks are described in the following sections.
|
||||
|
||||
.. note::
|
||||
|
||||
If any packet is received with an invalid checksum, a specific flow
|
||||
takes place for the sender to be able to understand the situation and
|
||||
resend said packet.
|
||||
|
||||
This sub-flow is considered part of the "sending a packet" flow, and
|
||||
must be treated within this logic.
|
||||
|
||||
See :ref:`seven-report-invalid-checksum` for more information.
|
||||
|
||||
.. note::
|
||||
|
||||
In between any of the packet sending steps, if the side expected to send
|
||||
a packet takes too long to do so, a sub flow takes place to check if the
|
||||
other side is still present.
|
||||
|
||||
See :ref:`seven-check-link` for more information.
|
||||
|
||||
.. _seven-report-invalid-checksum:
|
||||
|
||||
Reporting invalid checksums
|
||||
---------------------------
|
||||
|
||||
In case a packet has an invalid checksum, it may mean that the packet has
|
||||
been corrupted by the medium lying under the link. In such cases, a specific
|
||||
flow takes place so that the sender of the packet can resend the packet.
|
||||
|
||||
An example flow where the active side sends the corrupted packet
|
||||
is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command with invalid checksum
|
||||
passive->>active: Error with '01' subtype
|
||||
active->>passive: Same command with valid checksum
|
||||
Note over active,passive: ...
|
||||
|
||||
An example flow where the passive side sends the corrupted packet is
|
||||
the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command
|
||||
passive->>active: ACK with invalid checksum
|
||||
active->>passive: Error with '01' subtype
|
||||
passive->>active: ACK with valid checksum
|
||||
Note over active,passive: ...
|
||||
|
||||
.. _seven-init-link:
|
||||
|
||||
Initiating the link
|
||||
-------------------
|
||||
|
||||
When opening a link to a calculator that hasn't received any packets yet,
|
||||
the PC must initialize the link using this flow, which is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Initial check
|
||||
passive->>active: ACK
|
||||
|
||||
The initial check packet is a check packet of subtype ``00``; see
|
||||
:ref:`seven-check-packet` for more information.
|
||||
|
||||
.. _seven-terminate-link:
|
||||
|
||||
Terminating the link
|
||||
--------------------
|
||||
|
||||
When closing a link to a calculator that we don't plan on sending packets
|
||||
anymore, we are expected to terminate the link using the following flow:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Terminate
|
||||
passive->>active: ACK
|
||||
|
||||
See :ref:`seven-terminate-packet` for more information on the terminate packet.
|
||||
|
||||
.. _seven-check-link:
|
||||
|
||||
Checking up on the link
|
||||
-----------------------
|
||||
|
||||
In order to detect a "deaf" passive side, the active side must run the
|
||||
following flow if inactive for more than 6 minutes:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Regular check
|
||||
passive->>active: ACK
|
||||
|
||||
The regular check is a check packet with the ``01`` subtype; see
|
||||
:ref:`seven-check-packet` for more information.
|
||||
|
||||
If this flow is not run and the connection is active for more than 6 minutes,
|
||||
the passive side terminates the connection.
|
||||
|
||||
.. _seven-confirm-overwrite:
|
||||
|
||||
Confirming or rejecting overwrite
|
||||
---------------------------------
|
||||
|
||||
Some commands, such as :ref:`seven-command-45`, may require overwrite
|
||||
confirmation in case the file already exists on the calculator. In such
|
||||
cases, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command with OW set to '00'
|
||||
passive->>active: Overwrite confirmation requested
|
||||
active->>active: Request user confirmation
|
||||
|
||||
alt User confirms overwrite
|
||||
active->>passive: Confirm overwrite
|
||||
passive->>active: Acknowledge
|
||||
else
|
||||
active->>passive: Deny overwrite
|
||||
passive->>active: Acknowledge
|
||||
end
|
||||
|
||||
The packets used in this sequence are the following:
|
||||
|
||||
* The overwrite confirmation request is represented as a NAK packet with
|
||||
the ``02`` subtype; see :ref:`seven-nak-packet`.
|
||||
* The overwrite confirmation is represented as an ACK packet with the
|
||||
``01`` subtype; see :ref:`seven-ack-packet`.
|
||||
* The overwrite denial is represented as a NAK packet with the ``03``
|
||||
subtype; see :ref:`seven-nak-packet`.
|
||||
* Both the overwrite confirmation acknowledgement and overwrite denial
|
||||
acknowledgement are represented as an ACK packet with the ``00`` subtype;
|
||||
see :ref:`seven-ack-packet`.
|
||||
|
||||
.. _seven-transmit-data:
|
||||
|
||||
Transferring data
|
||||
-----------------
|
||||
|
||||
Say that an active and a passive side have agreed on a data exchange through
|
||||
commands, and have already swapped if necessary. In order to transfer data,
|
||||
the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
loop Data left to transmit
|
||||
active->>passive: Data packet
|
||||
passive->>active: ACK
|
||||
end
|
||||
|
||||
Data packets are described in :ref:`seven-data-packet`.
|
||||
|
||||
.. note::
|
||||
|
||||
Note that the number of data packets must be known in advance, since all
|
||||
data packets contain both the sequence number and the total sequence count,
|
||||
e.g. "packet 51/128".
|
||||
|
||||
In order to know the number of packets an original buffer can take, due
|
||||
to escaping concerns, it is highly recommended to consider that all packets
|
||||
contain up to 256 bytes, except the last one that may contain less.
|
||||
For example:
|
||||
|
||||
* 500 bytes will be represented as 2 data packets (one of 256 bytes,
|
||||
one of 244 bytes).
|
||||
* 512 bytes will be represented as 2 data packets (both of 256 bytes).
|
||||
* 1055 bytes will be represented as 5 data packets (four of 256 bytes,
|
||||
one of 31 bytes).
|
||||
|
||||
Packet shifting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Packet shifting is a technique discovered in 2017 that makes data transfers
|
||||
faster. It consists in sending the next data packet before the acknowledgement
|
||||
for the previous one is received.
|
||||
|
||||
The flow becomes the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: First data packet
|
||||
|
||||
loop Data left to transmit
|
||||
active->>passive: Send data packet #N
|
||||
passive->>active: ACK for data packet #N - 1
|
||||
end
|
||||
|
||||
passive->>active: ACK for last data packet
|
||||
|
||||
.. warning::
|
||||
|
||||
This technique comes with its risks, especially the fact that it renders
|
||||
the link non-recoverable in case of bad packet checksum while it is
|
||||
in effect, since the packet correction flow assumes that no "normal"
|
||||
packet is sent after the problematic packet (while we have already sent
|
||||
the packet that comes after in the sequence).
|
||||
|
||||
In order to mitigate such risks while still employing the technique,
|
||||
Cahute disables packet shifting on serial links, i.e. only enables it
|
||||
on USB and UAS (SCSI) links.
|
||||
|
||||
.. _seven-request-transfer:
|
||||
|
||||
Requesting data transfer(s)
|
||||
---------------------------
|
||||
|
||||
When requesting a file or some data generally from the calculator,
|
||||
the usual flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Original Active Side
|
||||
Participant passive as Original Passive Side
|
||||
|
||||
active->>passive: Command (transfer request)
|
||||
passive->>active: ACK
|
||||
active->>passive: Roleswap
|
||||
|
||||
Note over active,passive: Active side becomes passive, and vice versa
|
||||
|
||||
loop Transfer required
|
||||
passive->>active: Command (transfer)
|
||||
active->>passive: ACK
|
||||
Note over active,passive: Data flow from calculator to PC
|
||||
end
|
||||
|
||||
passive->>active: Roleswap
|
||||
|
||||
Note over active,passive: Original active side becomes active again
|
||||
|
||||
This applies to several use cases, but an example one is the PC requesting
|
||||
a file from the calculator's flash memory. The transfer request command for
|
||||
such a case is :ref:`seven-command-24`, and the transfer command emitted
|
||||
by the calculator after the roleswap is :ref:`seven-command-25`.
|
||||
|
||||
.. note::
|
||||
|
||||
The transfer request can lead to multiple commands from the calculator,
|
||||
e.g. with commands such as :ref:`seven-command-29` that will spawn
|
||||
one command and associated data transmission by file in the main memory.
|
||||
|
||||
.. _seven-get-device-information:
|
||||
|
||||
Requesting device information
|
||||
-----------------------------
|
||||
|
||||
While in the "requesting transfer" rationale, the flow to get the device
|
||||
information using command :ref:`seven-command-01` is different from the
|
||||
usual solution applied for this case:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '01'
|
||||
passive->>active: EACK with device information
|
||||
|
||||
.. note::
|
||||
|
||||
This is likely to avoid a more complex flow with a roleswap, as described
|
||||
in :ref:`seven-request-transfer`, or because the aforementioned flow did
|
||||
not exist when this command was conceived.
|
||||
|
||||
.. _seven-update-serial-params:
|
||||
|
||||
Updating serial parameters
|
||||
--------------------------
|
||||
|
||||
If the link is established on a serial stream, it is possible to negotiate
|
||||
different serial parameters with the calculator dynamically using
|
||||
:ref:`seven-command-02`, using the following flow:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '02'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
|
||||
Note over active,passive: Both sides update their<br />serial parameters before<br />their next packet exchanges.
|
||||
end
|
||||
|
||||
The only elements that can be updated are the serial speed in bauds, the
|
||||
parity, and the number of stop bits (1 or 2).
|
||||
|
||||
The serial speeds are limited to the following speeds (or baud rates):
|
||||
300, 600, 1200, 2400, 4800, 9600 (*by default*), 19200, 38400, 57600 and
|
||||
115200 bauds.
|
||||
|
||||
.. warning::
|
||||
|
||||
Depending on the quality of the serial cable (or USB to serial cable
|
||||
/ converter), higher speeds may cause more corruption to occur, causing
|
||||
a lot of resends and hence, being less efficient than lower baud rates.
|
|
@ -0,0 +1,78 @@
|
|||
.. _seven-hardware-identifiers:
|
||||
|
||||
Known hardware identifiers for Protocol 7.00
|
||||
============================================
|
||||
|
||||
All known Protocol 7.00 environments support command :ref:`seven-command-01`.
|
||||
Several people have used this command to obtain information using their
|
||||
calculator in different link modes; this document inventories the results.
|
||||
|
||||
Bootcodes
|
||||
---------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Hardware identifier
|
||||
- Devices
|
||||
- Link
|
||||
* - ``Gy362000``
|
||||
- fx-7400GII, fx-9750G(II), fx-9860GII SD
|
||||
- yes
|
||||
* - ``Gy363000``
|
||||
- fx-7400GII-2, fx-9750GII-2, fx-9860G(II(-2)), fx-9860G slim,
|
||||
fx-9860GII-2, Graph 35+E, Graph 75+E
|
||||
- no
|
||||
* - ``Gy490000``
|
||||
- fx-7400GII-2
|
||||
- yes
|
||||
|
||||
Bootcodes do **not** support restart-related commands :ref:`seven-command-00`
|
||||
and :ref:`seven-command-06`.
|
||||
Bootcodes with ``Link`` support command :ref:`seven-command-02`.
|
||||
|
||||
Devices
|
||||
-------
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Hardware identifier
|
||||
- Devices
|
||||
- Backup
|
||||
* - ``Gy362006``
|
||||
- fx-9750GII, Graph 35+ (SH3)
|
||||
- no
|
||||
* - ``Gy362007``
|
||||
- fx-9750GII-2, Graph 35+ (SH4), Graph 35+E (OS < 2.05)
|
||||
- no
|
||||
* - ``Gy36200F``
|
||||
- Graph 35+E
|
||||
- no
|
||||
* - ``Gy363006``
|
||||
- fx-9860GII, Graph 75 (SH3)
|
||||
- yes
|
||||
* - ``Gy363007``
|
||||
- fx-9860GII-2, Graph 75 (SH4), Graph 95 (SH4)
|
||||
- no
|
||||
* - ``Gy36300F``
|
||||
- Graph 75+E
|
||||
- no
|
||||
* - ``Ly755000``
|
||||
- fx-CG20, Prizm
|
||||
- no
|
||||
|
||||
All devices support main memory (:ref:`seven-command-20` to
|
||||
:ref:`seven-command-33`) and reset related commands (:ref:`seven-command-00`
|
||||
and :ref:`seven-command-06`).
|
||||
|
||||
If there is at least one filesystem, flash commands
|
||||
(:ref:`seven-command-40` to :ref:`seven-command-4E`, and
|
||||
:ref:`seven-command-51`) are supported.
|
||||
Two calculators that have different filesystems may have the same hardware
|
||||
identifier, so it cannot be used for this (e.g. Graph 75 and Graph 95, the
|
||||
latter having an SD port).
|
||||
|
||||
Devices with ``Backup`` support backup commands (:ref:`seven-command-4F`,
|
||||
:ref:`seven-command-50`, and :ref:`seven-command-52` to
|
||||
:ref:`seven-command-55`).
|
|
@ -0,0 +1,420 @@
|
|||
Protocol 7.00 packet format
|
||||
===========================
|
||||
|
||||
All packets with Protocol 7.00 have the following header:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 1 B
|
||||
- Type (*T*)
|
||||
- Basic purpose of the packet
|
||||
- 0x00 to 0x1F
|
||||
* - 2 B
|
||||
- Subtype (*ST*)
|
||||
- Specific function of the packet
|
||||
- 2-chars :ref:`seven-ascii-hex` value, ``00`` to ``FF``
|
||||
* - 1 B
|
||||
- Extended (*EX*)
|
||||
- Whether data is attached to the packet
|
||||
- 1-char :ref:`seven-ascii-hex` value, ``0`` or ``1``
|
||||
|
||||
If the packet is extended, i.e. if *EX* is set to ``1``, the following
|
||||
extension is appended to the header:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 4 B
|
||||
- Data size (*DS*)
|
||||
- Size of the *D* field
|
||||
- 4-char :ref:`seven-ascii-hex` value, ``0000`` to ``FFFF``
|
||||
* - *DS* B
|
||||
- Data (*D*)
|
||||
- Additional data
|
||||
- :ref:`seven-5c-padding` encoded data
|
||||
|
||||
All packets have the following footer:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 2 B
|
||||
- Checksum (*CS*)
|
||||
- Checksum for integrity check
|
||||
- 2-char :ref:`seven-ascii-hex` value, ``00`` to ``FF``
|
||||
|
||||
.. _seven-checksum:
|
||||
|
||||
The checksum can be obtained or verified by summing all bytes going from
|
||||
*ST* to *D* if present, or *EX* if not, and adding 1 to its bitwise
|
||||
complement.
|
||||
|
||||
The interpretation of the packet depends on the value of *T*.
|
||||
See the following sections for more information.
|
||||
|
||||
``0x01`` -- Command packet
|
||||
--------------------------
|
||||
|
||||
The command packet reflects an order given by the active side to the
|
||||
passive side. The packet subtype (*ST*) contains the command code.
|
||||
|
||||
If the packet is extended, the packet data (*D*) is **usually** formatted
|
||||
the following way:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 2 B
|
||||
- Overwrite (*OW*)
|
||||
- Mode of operation if a file exists.
|
||||
- 2-char :ref:`seven-ascii-hex` value:
|
||||
|
||||
- ``00``: Request user confirmation.
|
||||
- ``01``: Terminate if exists.
|
||||
- ``02``: Force overwrite.
|
||||
* - 2 (0x02)
|
||||
- 2 B
|
||||
- Data type (*DT*)
|
||||
- Data type.
|
||||
- 2-char :ref:`seven-ascii-hex` value, ``00``.
|
||||
* - 4 (0x04)
|
||||
- 8 B
|
||||
- File size (*FS*)
|
||||
- Size of the file being transferred.
|
||||
- 8-char :ref:`seven-ascii-hex` value.
|
||||
* - 12 (0x0C)
|
||||
- 2 B
|
||||
- Data size 1 (*SD1*)
|
||||
- Size of *D1*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 14 (0x0E)
|
||||
- 2 B
|
||||
- Data size 2 (*SD2*)
|
||||
- Size of *D2*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 16 (0x10)
|
||||
- 2 B
|
||||
- Data size 3 (*SD3*)
|
||||
- Size of *D3*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 18 (0x12)
|
||||
- 2 B
|
||||
- Data size 4 (*SD4*)
|
||||
- Size of *D4*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 20 (0x14)
|
||||
- 2 B
|
||||
- Data size 5 (*SD5*)
|
||||
- Size of *D5*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 22 (0x16)
|
||||
- 2 B
|
||||
- Data size 6 (*SD6*)
|
||||
- Size of *D6*
|
||||
- 2-char :ref:`seven-ascii-hex` value.
|
||||
* - 24 (0x16)
|
||||
- *SD1* B
|
||||
- Data 1 (*D1*)
|
||||
- First argument
|
||||
-
|
||||
* - 24 (0x16) + *SD1*
|
||||
- *SD2* B
|
||||
- Data 2 (*D2*)
|
||||
- Second argument
|
||||
-
|
||||
* - 24 (0x16) + *SD1* + *SD2*
|
||||
- *SD3* B
|
||||
- Data 3 (*D3*)
|
||||
- Third argument
|
||||
-
|
||||
* - 24 (0x16) + *SD1* + *SD2* + *SD3*
|
||||
- *SD4* B
|
||||
- Data 4 (*D4*)
|
||||
- Fourth argument
|
||||
-
|
||||
* - 24 (0x16) + *SD1* + *SD2* + *SD3* + *SD4*
|
||||
- *SD5* B
|
||||
- Data 5 (*D5*)
|
||||
- Fifth argument
|
||||
-
|
||||
* - 24 (0x16) + *SD1* + *SD2* + *SD3* + *SD4* + *SD5*
|
||||
- *SD6* B
|
||||
- Data 6 (*D6*)
|
||||
- Sixth argument
|
||||
-
|
||||
|
||||
.. warning::
|
||||
|
||||
There is an exception, i.e. a command that uses a different payload format:
|
||||
command :ref:`seven-command-56`.
|
||||
|
||||
.. _seven-data-packet:
|
||||
|
||||
``0x02`` -- Data packet
|
||||
-----------------------
|
||||
|
||||
The data packet is used to transfer "raw" data, as described in
|
||||
:ref:`seven-transmit-data`.
|
||||
|
||||
The packet subtype (*ST*) must be the same as the subtype (*ST*) of the
|
||||
command that has initiated the data transmission; e.g. if the data flow has
|
||||
been initiated following command :ref:`seven-command-25`, all data packets
|
||||
in the corresponding flow must bear the *ST* ``25``.
|
||||
|
||||
All data packets are expected to be extended (i.e. *EX* is set to ``1``).
|
||||
The layout of *D* is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 4 B
|
||||
- Total number (*TN*)
|
||||
- Total number of data packets in current transmission
|
||||
- 4-char :ref:`seven-ascii-hex` value, ``0001`` to ``FFFF``.
|
||||
* - 4 B
|
||||
- Current number (*CN*)
|
||||
- Current data packet number in current transmission
|
||||
- 4-char :ref:`seven-ascii-hex` value, ``0001`` to ``FFFF``.
|
||||
* - 0-512 B
|
||||
- Contents (*DD*)
|
||||
- Contents of data packet
|
||||
-
|
||||
|
||||
Note that since 512 bytes is the maximum transmittable amount, and that
|
||||
:ref:`seven-5c-padding` can only double the data size, the maximum size
|
||||
of transmitted data within one data packet is 256 bytes.
|
||||
|
||||
``0x03`` -- Roleswap packet
|
||||
---------------------------
|
||||
|
||||
The roleswap packet indicates a roleswap, and is used for transfer requests;
|
||||
see :ref:`seven-request-transfer` for more information.
|
||||
|
||||
Such packets will never be extended, and will never have another subtype
|
||||
than ``00``.
|
||||
|
||||
.. _seven-check-packet:
|
||||
|
||||
``0x05`` -- Check packet
|
||||
------------------------
|
||||
|
||||
This covers two different packet types, depending on the subtype (*ST*):
|
||||
|
||||
* If *ST* is ``00``, this is an initial check packet used to establish
|
||||
communication with the calculator. See :ref:`seven-init-link` for
|
||||
more information.
|
||||
* If *ST* is ``01``, this is a regular check packet used to check if
|
||||
the link is still up with the calculator. See :ref:`seven-check-link`
|
||||
for more information.
|
||||
|
||||
This packet is not expected to be extended, i.e. *EX* should be ``0``.
|
||||
|
||||
.. _seven-ack-packet:
|
||||
|
||||
``0x06`` -- Acknowledgement (ACK) packet
|
||||
----------------------------------------
|
||||
|
||||
This covers two different packet types, depending on the subtype (*ST*):
|
||||
|
||||
* If *ST* is ``00``, this is a basic acknowledgement whose role can be
|
||||
interpreted differently depending on the flow. It is not expected to be
|
||||
extended, i.e. *EX* should be ``0``.
|
||||
* If *ST* is ``01``, this is an overwrite confirmation; see
|
||||
:ref:`seven-confirm-overwrite` for more details on the related flow.
|
||||
* If *ST* is ``02``, this is an extended acknowledgement (EACK), providing
|
||||
additional information, i.e. the packet is extended and *EX* should be
|
||||
set to ``1``.
|
||||
|
||||
**This is only used in the flow to get device information**; see
|
||||
:ref:`seven-get-device-information` and :ref:`seven-command-01`
|
||||
for more information.
|
||||
* If *ST* is ``03``, this means the acknowledge packet also marks the end
|
||||
of the communication.
|
||||
|
||||
The payload for an extended acknowledgement is the following:
|
||||
|
||||
If *ST* is set to ``02``, the packet data (*D*) is expected to be 164 (0xA4)
|
||||
bytes long, and structured the following way:
|
||||
|
||||
If *ST* is set to ``02``, the packet data (*D*) is expected to be one of:
|
||||
|
||||
* 164 (0xA4) bytes long for fx-9860G and compatible models.
|
||||
* 188 (0xBC) bytes long for the fx-CG family of models.
|
||||
|
||||
The format of the 164 bytes long payload is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 8 B
|
||||
- Hardware Identifier (*HWID*)
|
||||
- Hardware identifier for the calculator.
|
||||
- See :ref:`seven-hardware-identifiers` for known hardware identifiers.
|
||||
* - 8 (0x08)
|
||||
- 16 B
|
||||
- Processor Identifier (*CPUID*)
|
||||
- String describing the processor used by the calculator.
|
||||
Is known to be incorrect, it is recommended not to use this field.
|
||||
- ``RENESAS SH735501``
|
||||
* - 24 (0x18)
|
||||
- 8 B
|
||||
- Preprogrammed ROM capacity
|
||||
- Capacity of the preprogrammed ROM, in KB
|
||||
- 8-char **ASCII-DEC** value, e.g. ``00000000``.
|
||||
* - 32 (0x20)
|
||||
- 8 B
|
||||
- Flash ROM capacity
|
||||
- Capacity of the flash ROM, in KB
|
||||
- 8-char **ASCII-DEC** value, e.g. ``00004096``.
|
||||
* - 40 (0x28)
|
||||
- 8 B
|
||||
- RAM capacity
|
||||
- Capacity of the RAM, in KB
|
||||
- 8-char **ASCII-DEC** value, e.g. ``00000512``.
|
||||
* - 48 (0x30)
|
||||
- 16 B
|
||||
- Preprogrammed ROM version
|
||||
- Version of the preprogrammed ROM, as an OS version
|
||||
- ``xx.xx.xxxx`` + ``\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 64 (0x40)
|
||||
- 16 B
|
||||
- Boot code version
|
||||
- Version of the bootcode, as an OS version
|
||||
- ``xx.xx.xxxx`` + ``\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 80 (0x50)
|
||||
- 8 B
|
||||
- Boot code offset
|
||||
- Offset of the boot code on the ROM, as a 32-bit address.
|
||||
- 8-char :ref:`seven-ascii-hex` value.
|
||||
* - 88 (0x58)
|
||||
- 8 B
|
||||
- Boot code size
|
||||
- Size of the boot code, in KB.
|
||||
- 8-char :ref:`seven-ascii-hex` value.
|
||||
* - 96 (0x60)
|
||||
- 16 B
|
||||
- OS code version
|
||||
- Version of the OS, as an OS version
|
||||
- ``xx.xx.xxxx`` + ``\xFF\xFF\xFF\xFF\xFF\xFF``
|
||||
* - 112 (0x70)
|
||||
- 8 B
|
||||
- OS code offset
|
||||
- Offset of the OS on the ROM, as a 32-bit address.
|
||||
- 8-char :ref:`seven-ascii-hex` value.
|
||||
* - 120 (0x78)
|
||||
- 8 B
|
||||
- OS code size
|
||||
- Size of the OS on the ROM, in KB.
|
||||
- 8-char :ref:`seven-ascii-hex` value.
|
||||
* - 128 (0x80)
|
||||
- 4 B
|
||||
- Protocol version
|
||||
- Version of the protocol in use.
|
||||
- ``7.00``
|
||||
* - 132 (0x84)
|
||||
- 16 B
|
||||
- Product Identifier
|
||||
- Identifier of the calculator.
|
||||
- 8-char alphabetical (upper and lower case) identifier.
|
||||
* - 148 (0x94)
|
||||
- 16 B
|
||||
- User Name
|
||||
- Name set by the user in SYSTEM
|
||||
-
|
||||
|
||||
The format of the 164 bytes long payload is the following:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Field name
|
||||
- Description
|
||||
- Values
|
||||
* - 0 (0x00)
|
||||
- 148 B
|
||||
- ...
|
||||
- Equivalent to the 164 bytes long payload up to the Product Identifier,
|
||||
included.
|
||||
- See above.
|
||||
* - 148 (0x94)
|
||||
- 20 B
|
||||
- User Name
|
||||
- Set by the user in SYSTEM.
|
||||
-
|
||||
* - 168 (0xA8)
|
||||
- 20 B
|
||||
- Organisation Name
|
||||
- Set by the user in SYSTEM.
|
||||
-
|
||||
|
||||
.. _seven-nak-packet:
|
||||
|
||||
``0x15`` -- Negative acknowledgement (NAK) packet
|
||||
-------------------------------------------------
|
||||
|
||||
This covers multiple packet types, depending on the subtype (*ST*):
|
||||
|
||||
* If *ST* is ``00``, a default error is returned.
|
||||
* If *ST* is ``01``, the previously received packet is invalid and requires
|
||||
resending from the other side. See :ref:`seven-report-invalid-checksum`
|
||||
for more information on the usage of this error.
|
||||
* If *ST* is ``02``, the operation requires an overwrite confirmation;
|
||||
see :ref:`seven-confirm-overwrite` for more details on the related flow.
|
||||
* If *ST* is ``03``, the active side is signalling an overwrite rejection from
|
||||
the user to the passive side; see :ref:`seven-confirm-overwrite` for more
|
||||
details on the related flow.
|
||||
* If *ST* is ``04``, the error is a generic error that terminates the link.
|
||||
* If *ST* is ``05``, the memory is full and the link is also terminated.
|
||||
|
||||
.. _seven-terminate-packet:
|
||||
|
||||
``0x18`` -- Terminate packet
|
||||
----------------------------
|
||||
|
||||
This data packet is used by the active side to signal termination of
|
||||
the link usage. The subtype (*ST*) represents the reason for termination:
|
||||
|
||||
* *ST* being set to ``00`` is the default case.
|
||||
* If *ST* is set to ``01``, it means that the user has requested
|
||||
termination from either the active or passive side.
|
||||
* If *ST* is set to ``02``, it means that the termination is due to
|
||||
timeouts, likely due to checking flows having failed; see
|
||||
:ref:`seven-check-link` for more information.
|
||||
* If *ST* is set to ``03``, it means that the termination is due to
|
||||
an overwrite request having been denied by the user on the active side.
|
||||
|
||||
All termination packets should not be extended, i.e. *EX* should be ``0``.
|
||||
|
||||
See :ref:`seven-terminate-link` for more information on the link
|
||||
termination flow.
|
|
@ -0,0 +1,43 @@
|
|||
Specific formats for Protocol 7.00
|
||||
==================================
|
||||
|
||||
Protocol 7.00 is made so that the data is always printable.
|
||||
There only notable exception for this is the basic packet type, i.e. the first
|
||||
byte of all basic packets, which in most if not all cases is lesser
|
||||
than 0x20.
|
||||
|
||||
In all other places, the protocol takes specific dispositions to make the
|
||||
packets printable, described in the following sections.
|
||||
|
||||
.. _seven-ascii-hex:
|
||||
|
||||
ASCII-HEX
|
||||
~~~~~~~~~
|
||||
|
||||
Numbers are represented with ASCII-HEX, i.e. by providing the ASCII-encoded
|
||||
version of their hexadecimal representation. For example, 3886 (0xF2E) is
|
||||
represented as ``0F2E`` (0x30, 0x46, 0x32, 0x45) on four bytes, or
|
||||
``00000F2E`` (0x30, 0x30, 0x30, 0x30, 0x30, 0x46, 0x32, 0x45) on eight.
|
||||
|
||||
.. _seven-5c-padding:
|
||||
|
||||
0x5C padding
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Raw data may be escaped using "0x5C padding", i.e.:
|
||||
|
||||
* Characters in the 0x00-0x1F range have 0x20 added to their value, and
|
||||
are prefixed by ``\`` (0x5C). For example, 0x06 becomes ``\&`` (0x5C,
|
||||
0x26).
|
||||
* Character ``\`` (0x5C) itself is prefixed by another ``\`` (0x5C),
|
||||
but does not have a bump, i.e. ``\`` (0x5C) becomes ``\\`` (0x5C).
|
||||
|
||||
When decode such padded data, if a ``\`` (0x5C) is encountered, there is
|
||||
necessarily a character afterwards. The obtained character for the group of
|
||||
two characters depends on the second character:
|
||||
|
||||
* If the second character is ``\`` (0x5C), then the result must be
|
||||
``\`` (0x5C).
|
||||
* Otherwise, the resulting byte is the ASCII code of the second character,
|
||||
to which we substract 0x20. For example, if ``\&`` (0x5C, 0x26) is
|
||||
encountered, the final byte must be 0x26 minus 0x20, i.e. 0x06.
|
|
@ -0,0 +1,280 @@
|
|||
Protocol 7.00 use cases
|
||||
=======================
|
||||
|
||||
This document inventories use cases of Protocol 7.00 that are exploited by
|
||||
the library and command-line utilities.
|
||||
|
||||
.. _seven-send-file-to-storage:
|
||||
|
||||
Send a file to storage
|
||||
----------------------
|
||||
|
||||
In order to send a file to storage, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant user as User
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '45'
|
||||
|
||||
alt Overwrite confirmation is required
|
||||
passive->>active: Overwrite confirmation requested
|
||||
active->>user: Request user confirmation
|
||||
user->>active: Confirm or reject
|
||||
|
||||
alt User confirms overwrite
|
||||
active->>passive: Confirm overwrite
|
||||
else
|
||||
active->>passive: Reject overwrite
|
||||
end
|
||||
end
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
|
||||
Note over active,passive: Data transfer flow from<br />active side to passive
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-45`;
|
||||
* :ref:`seven-confirm-overwrite`;
|
||||
* :ref:`seven-transmit-data`.
|
||||
|
||||
This flow is used by ``p7 send``; see the :ref:`p7-send` for more information.
|
||||
|
||||
.. _seven-request-file-from-storage:
|
||||
|
||||
Request a file from storage
|
||||
---------------------------
|
||||
|
||||
In order to request a file to storage, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Original Active Side
|
||||
Participant passive as Original Passive Side
|
||||
|
||||
active->>passive: Command '44'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
active->>passive: Roleswap
|
||||
|
||||
passive->>active: Command '45'
|
||||
active->>passive: Acknowledge
|
||||
|
||||
Note over active,passive: Data transfer flow from<br />original passive side to active
|
||||
|
||||
passive->>active: Roleswap
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-44`;
|
||||
* Command :ref:`seven-command-45`;
|
||||
* :ref:`seven-request-transfer`;
|
||||
* :ref:`seven-transmit-data`.
|
||||
|
||||
This flow is used by ``p7 get``; see the :ref:`p7-get` for more information.
|
||||
|
||||
.. _seven-copy-file-on-storage:
|
||||
|
||||
Copy a file to another on storage
|
||||
---------------------------------
|
||||
|
||||
In order to copy a file on storage, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '48'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-48`.
|
||||
|
||||
This flow is used by ``p7 copy``; see the :ref:`p7-copy` for more information.
|
||||
|
||||
.. _seven-delete-file-on-storage:
|
||||
|
||||
Delete a file from storage
|
||||
--------------------------
|
||||
|
||||
In order to delete a file on storage, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '46'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-46`.
|
||||
|
||||
This flow is used by ``p7 delete``; see the :ref:`p7-delete`
|
||||
for more information.
|
||||
|
||||
.. _seven-list-files-on-storage:
|
||||
|
||||
List files on storage
|
||||
---------------------
|
||||
|
||||
In order to list files on storage, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Original Active Side
|
||||
Participant passive as Original Passive Side
|
||||
|
||||
active->>passive: Command '4D'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
active->>passive: Roleswap
|
||||
|
||||
loop All file information has not been sent
|
||||
passive->>active: Command '4E'
|
||||
active->>passive: Acknowledge
|
||||
end
|
||||
|
||||
passive->>active: Roleswap
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-4D`;
|
||||
* Command :ref:`seven-command-4E`;
|
||||
* :ref:`seven-request-transfer`.
|
||||
|
||||
This flow is used by ``p7 list``; see the :ref:`p7-list` for more information.
|
||||
|
||||
.. _seven-reset-storage:
|
||||
|
||||
Reset a storage device
|
||||
----------------------
|
||||
|
||||
In order to reset a storage device, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '4A'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-4A`.
|
||||
|
||||
This flow is used by ``p7 reset``; see the :ref:`p7-reset`
|
||||
for more information.
|
||||
|
||||
.. _seven-optimize-storage:
|
||||
|
||||
Optimize a storage device
|
||||
-------------------------
|
||||
|
||||
In order to optimize a storage device, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '51'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
end
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-51`.
|
||||
|
||||
This flow is used by ``p7 optimize``; see the :ref:`p7-optimize` for more
|
||||
information.
|
||||
|
||||
.. _seven-upload-and-run:
|
||||
|
||||
Upload and run an executable program
|
||||
------------------------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a dangerous flow, and is only documented here for completeness.
|
||||
Programs suitable for this command, nicknamed "Update.exe", are crafted
|
||||
in a very specific way, and you should not attempt to make your own.
|
||||
|
||||
In order to upload and run an executable program, the flow is the following:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
sequenceDiagram
|
||||
Participant active as Active Side
|
||||
Participant passive as Passive Side
|
||||
|
||||
active->>passive: Command '56'
|
||||
|
||||
alt Error has occurred
|
||||
passive->>active: Error
|
||||
else
|
||||
passive->>active: Acknowledge
|
||||
|
||||
Note over active,passive: Data transfer from active to passive
|
||||
end
|
||||
|
||||
If successful, the last acknowledgement from the data transfer will have
|
||||
the special subtype ``03``, which means that the communication is terminated
|
||||
as control of the device is handed over to the program.
|
||||
|
||||
This use case is employed for updating the calculator, by uploading and running
|
||||
special programs whose role is to open a USB or serial link, and receive and
|
||||
flash the new OS at the command of the host. This has also been employed by
|
||||
the community to do the same, such as with fxRemote_.
|
||||
|
||||
For more information, consult the following sections:
|
||||
|
||||
* Command :ref:`seven-command-56`;
|
||||
* :ref:`seven-transmit-data`.
|
||||
|
||||
.. _fxRemote: https://tiplanet.org/forum/archives_voir.php?id=4484
|
|
@ -0,0 +1,25 @@
|
|||
.. _protocol-ums:
|
||||
|
||||
USB Mass Storage (UMS) and proprietary extensions for fx-CG calculators
|
||||
=======================================================================
|
||||
|
||||
In order to behave like any other USB-attached storage with their "USB Key"
|
||||
communications mode, fx-CG calculators implement `USB Mass Storage`_ (UMS)
|
||||
with `Bulk-Only Transport`_.
|
||||
|
||||
The following sections describe CASIO's usage of UMS in this context.
|
||||
|
||||
.. note::
|
||||
|
||||
Extensions to the SCSI protocol embedded within CASIO's UMS implementation
|
||||
still support a stream interface for communicating using Protocol 7.00
|
||||
or Protocol 7.00 Screenstreaming over UMS; see
|
||||
:ref:`ums-custom-commands` for more information.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ums/custom-commands
|
||||
|
||||
.. _USB Mass Storage: https://en.wikipedia.org/wiki/USB_mass_storage_device_class
|
||||
.. _Bulk-Only Transport: https://www.usb.org/sites/default/files/usbmassbulk_10.pdf
|
|
@ -0,0 +1,133 @@
|
|||
.. _ums-custom-commands:
|
||||
|
||||
Custom SCSI commands for CASIO's USB Mass Storage implementation
|
||||
================================================================
|
||||
|
||||
CASIO makes use of the ``C0h`` to ``FFh`` `vendor-specific range`_ to
|
||||
implement its own SCSI commands.
|
||||
|
||||
.. _ums-command-c0:
|
||||
|
||||
``0xC0`` -- Poll status
|
||||
-----------------------
|
||||
|
||||
This command is a 16-byte command that is run to poll the device's status.
|
||||
The command format is the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Description
|
||||
- Value
|
||||
* - 0 (0x00)
|
||||
- 1 B
|
||||
- Command code.
|
||||
- ``0xC0``
|
||||
* - 1 (0x01)
|
||||
- 15 B
|
||||
- Reserved.
|
||||
- Must be set to ``0x00``.
|
||||
|
||||
The command prompts the device to answer with a 16-byte device status,
|
||||
with the following format:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Description
|
||||
- Value
|
||||
* - 0 (0x00)
|
||||
- 1 B
|
||||
- Unknown.
|
||||
- Set to ``0xD0``.
|
||||
* - 1 (0x01)
|
||||
- 5 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
* - 6 (0x06)
|
||||
- 2 B
|
||||
- Amount of available bytes to be requested.
|
||||
- Big endian 16-bit integer.
|
||||
* - 8 (0x08)
|
||||
- 2 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
* - 10 (0x0A)
|
||||
- 2 B
|
||||
- Activity status.
|
||||
- Big endian 16-bit integer.
|
||||
* - 12 (0x0C)
|
||||
- 4 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
|
||||
.. _ums-command-c1:
|
||||
|
||||
``0xC1`` -- Request available data
|
||||
----------------------------------
|
||||
|
||||
This command is a 16-byte long command that is run to read available data.
|
||||
The command format is the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Description
|
||||
- Value
|
||||
* - 0 (0x00)
|
||||
- 1 B
|
||||
- Command code.
|
||||
- ``0xC1``
|
||||
* - 1 (0x01)
|
||||
- 5 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
* - 6 (0x06)
|
||||
- 2 B
|
||||
- Requested bytes count.
|
||||
- Big endian 16-bit integer.
|
||||
* - 8 (0x08)
|
||||
- 8 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
|
||||
The command prompts the device to answer with the requested data.
|
||||
|
||||
.. _ums-command-c2:
|
||||
|
||||
``0xC2`` -- Send data
|
||||
---------------------
|
||||
|
||||
This command is a 16-byte long command that is run to write data to the
|
||||
calculator. The command format is the following:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - Offset
|
||||
- Size
|
||||
- Description
|
||||
- Value
|
||||
* - 0 (0x00)
|
||||
- 1 B
|
||||
- Command code.
|
||||
- ``0xC2``
|
||||
* - 1 (0x01)
|
||||
- 5 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
* - 6 (0x06)
|
||||
- 2 B
|
||||
- Bytes count.
|
||||
- Big endian 16-bit integer.
|
||||
* - 8 (0x08)
|
||||
- 8 B
|
||||
- Reserved.
|
||||
- Set to ``0x00``.
|
||||
|
||||
The command should be accompanied with the data to send.
|
||||
|
||||
.. _Vendor-specific range: https://en.wikipedia.org/wiki/SCSI_command#SCSI_command_lengths
|
|
@ -0,0 +1,51 @@
|
|||
.. _usb-detection:
|
||||
|
||||
USB detection for CASIO calculators
|
||||
===================================
|
||||
|
||||
When looking for CASIO calculators, the following vendor and product
|
||||
identifiers (VID/PID) can be used:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Vendor ID
|
||||
- Product ID
|
||||
- Interface class
|
||||
- Description
|
||||
* - ``07cf``
|
||||
- ``6101``
|
||||
- ``255`` (Vendor-Specific)
|
||||
- Graph 35+/75/85/95, fx-9860G Slim, Classpad 300
|
||||
* - ``07cf``
|
||||
- ``6102``
|
||||
- ``8`` (Mass Storage)
|
||||
- Classpad 330+, fx-CG20, fx-CP400, fx-CP400+E
|
||||
|
||||
The interface class ``255`` is used when the device presents protocol 7.00
|
||||
directly, while the interface class ``8`` is used in "USB key" mode, i.e.
|
||||
when the file system and main memory are presented using SCSI.
|
||||
|
||||
.. note::
|
||||
|
||||
For reference, the following USB serial cables have also be encountered
|
||||
in the wild:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Vendor ID
|
||||
- Product ID
|
||||
- Description
|
||||
* - ``0711``
|
||||
- ``0230``
|
||||
- SB-88 serial cable (official CASIO cable).
|
||||
* - ``0bda``
|
||||
- ``5606``
|
||||
- Util-Pocket (defunct alternative vendor) serial cable.
|
||||
Uses an USB serial converter from FTDI_.
|
||||
|
||||
Note however that these should be used through the system's serial
|
||||
bus interface rather than directly.
|
||||
|
||||
.. _FTDI: https://ftdichip.com/
|
|
@ -0,0 +1,37 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef CAHUTE_H
|
||||
#define CAHUTE_H 1
|
||||
#include <cahute/cdefs.h>
|
||||
#include <cahute/detection.h>
|
||||
#include <cahute/error.h>
|
||||
#include <cahute/link.h>
|
||||
#include <cahute/logging.h>
|
||||
#include <cahute/picture.h>
|
||||
#endif
|
|
@ -0,0 +1,332 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#if defined(OF)
|
||||
#elif defined(__STDC__) && __STDC__
|
||||
# define OF(CAHUTE__ARGS) CAHUTE__ARGS
|
||||
#else
|
||||
# define OF(CAHUTE__ARGS) ()
|
||||
#endif
|
||||
|
||||
#ifndef CAHUTE_CDEFS_H
|
||||
# define CAHUTE_CDEFS_H 1
|
||||
# include <cahute/config.h>
|
||||
|
||||
/* C++ declaration and namespace management. */
|
||||
# ifdef __cplusplus
|
||||
# define CAHUTE_BEGIN_NAMESPACE namespace "cahute" {
|
||||
# define CAHUTE_BEGIN_DECLS extern "C" {
|
||||
# define CAHUTE_END_DECLS }
|
||||
# define CAHUTE_END_NAMESPACE }
|
||||
# else
|
||||
# define CAHUTE_BEGIN_NAMESPACE
|
||||
# define CAHUTE_BEGIN_DECLS
|
||||
# define CAHUTE_END_DECLS
|
||||
# define CAHUTE_END_NAMESPACE
|
||||
# endif
|
||||
|
||||
CAHUTE_BEGIN_NAMESPACE
|
||||
|
||||
/* Macro to check the library version. */
|
||||
# define CAHUTE_PREREQ(CAHUTE__MAJ, CAHUTE__MIN) \
|
||||
((CAHUTE__MAJ) > (CAHUTE_MAJOR) \
|
||||
|| ((CAHUTE__MAJ) == (CAHUTE_MAJOR) && (CAHUTE__MIN) >= (CAHUTE_MINOR)) \
|
||||
)
|
||||
|
||||
/* ---
|
||||
* Compiler and language specific macros.
|
||||
* --- */
|
||||
|
||||
/* Macro to check if we have at least a specific version of GCC. */
|
||||
# if defined(CAHUTE_GNUC_PREREQ)
|
||||
# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define CAHUTE_GNUC_PREREQ(CAHUTE__MAJ, CAHUTE__MIN) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ \
|
||||
>= ((CAHUTE__MAJ) << 16) + (CAHUTE__MIN))
|
||||
# else
|
||||
# define CAHUTE_GNUC_PREREQ(CAHUTE__MAJ, CAHUTE__MIN) 0
|
||||
# endif
|
||||
|
||||
/* Macro to check if we have at least a specific version of MSC. */
|
||||
# if defined(CAHUTE_MSC_PREREQ) || defined(_MSC_VER)
|
||||
# define CAHUTE_MSC_PREREQ(CAHUTE__MAJ, CAHUTE__MIN) \
|
||||
(_MSC_VER >= (CAHUTE__MAJ) * 1000 + (CAHUTE__MIN))
|
||||
# else
|
||||
# define CAHUTE_MSC_PREREQ(CAHUTE__MAJ, CAHUTE__MIN) 0
|
||||
# endif
|
||||
|
||||
/* Export whether the function is deprecated. */
|
||||
# if CAHUTE_GNUC_PREREQ(3, 0)
|
||||
# define CAHUTE_DEPRECATED __attribute__((deprecated))
|
||||
# else
|
||||
# define CAHUTE_DEPRECATED
|
||||
# endif
|
||||
|
||||
/* Warn if the result is unused (Warn Unused Result). */
|
||||
# if CAHUTE_GNUC_PREREQ(4, 0)
|
||||
# define CAHUTE_WUR __attribute__((warn_unused_result))
|
||||
# elif CAHUTE_MSC_PREREQ(17, 0)
|
||||
# include <sal.h>
|
||||
# define CAHUTE_WUR _Check_return_
|
||||
# else
|
||||
# define CAHUTE_WUR
|
||||
# endif
|
||||
|
||||
/* Export the function to be used in an extern context. */
|
||||
# define CAHUTE_EXTERN(TYPE) extern TYPE
|
||||
|
||||
/* Make a function local. */
|
||||
# define CAHUTE_LOCAL(TYPE) static TYPE
|
||||
|
||||
/* Make a function local and inline. */
|
||||
# define CAHUTE_INLINE(TYPE) static inline TYPE
|
||||
|
||||
/* Make some data local. */
|
||||
# define CAHUTE_LOCAL_DATA(TYPE) static TYPE
|
||||
|
||||
/* Request non-null parameters.
|
||||
* CAHUTE_NNP is to be used inline, CAHUTE_NNP_ATTR is to be used after the
|
||||
* function declaration. Both should be defined for portability.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* int my_function(char const CAHUTE_NNPTR(my_string)) CAHUTE_NONNULL((1));
|
||||
*
|
||||
* Which can give any of, depending on the environment:
|
||||
*
|
||||
* int my_function(char const my_string[static 1]);
|
||||
* int my_function(char const *my_string) __attribute__((nonnull (1)));
|
||||
* int my_function(char const *my_string);
|
||||
*/
|
||||
/* TODO: Define these in some cases. */
|
||||
# define CAHUTE_NNPTR(NAME) *NAME
|
||||
# define CAHUTE_NONNULL(INDEXES)
|
||||
|
||||
/* Declare a structure. */
|
||||
# define CAHUTE_DECLARE_TYPE(NAME) \
|
||||
struct NAME; \
|
||||
typedef struct NAME NAME;
|
||||
|
||||
/* ---
|
||||
* Integer definitions.
|
||||
* --- */
|
||||
|
||||
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
# include <inttypes.h>
|
||||
# include <stdint.h>
|
||||
|
||||
/* `stdint.h` and `inttypes.h` are standard C99 headers.
|
||||
* `stdint.h` provides the `uintN_t` types, and
|
||||
* `inttypes.h` provides the `PRI[uxX]N` macros. */
|
||||
|
||||
typedef uint8_t cahute_u8;
|
||||
typedef uint16_t cahute_u16;
|
||||
typedef uint32_t cahute_u32;
|
||||
|
||||
# define CAHUTE_PRIu8 PRIu8
|
||||
# define CAHUTE_PRIx8 PRIx8
|
||||
# define CAHUTE_PRIX8 PRIX8
|
||||
# define CAHUTE_PRIu16 PRIu16
|
||||
# define CAHUTE_PRIx16 PRIx16
|
||||
# define CAHUTE_PRIX16 PRIX16
|
||||
# define CAHUTE_PRIu32 PRIu32
|
||||
# define CAHUTE_PRIx32 PRIx32
|
||||
# define CAHUTE_PRIX32 PRIX32
|
||||
|
||||
# else /* C89 */
|
||||
# include <limits.h>
|
||||
|
||||
/* Here, we ought to do some C89 hacking.
|
||||
* We'll use the `limits.h` definitions to try and guess which one of the
|
||||
* default types are the 8-bit, 16-bit and 32-bit integer. */
|
||||
|
||||
# define CAHUTE_P8 "hh"
|
||||
typedef unsigned char cahute_u8;
|
||||
|
||||
/* 16-bit integer. */
|
||||
|
||||
# if (USHRT_MAX > 0xffffUL)
|
||||
# error "No 16-bit type, exiting!"
|
||||
# endif
|
||||
# define CAHUTE_P16 "h"
|
||||
typedef unsigned short cahute_u16;
|
||||
|
||||
/* 32-bit integer. */
|
||||
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
# define CAHUTE_P32 ""
|
||||
typedef unsigned int cahute_u32;
|
||||
# elif (ULONG_MAX == 0xffffffffUL)
|
||||
# define CAHUTE_P32 "l"
|
||||
typedef unsigned long cahute_u32;
|
||||
# else
|
||||
|
||||
/* There is nothing between `char` and `short`, and `char` is always
|
||||
* byte-wide;
|
||||
*
|
||||
* `long long` is not defined in C89, and even if it can be used as a
|
||||
* compiler extension for C89, it is supposed to be 64-bit or more.
|
||||
* So basically we're running out of options here. */
|
||||
|
||||
# error "No 32-bit type, exiting!"
|
||||
# endif
|
||||
|
||||
# define CAHUTE_PRIu8 CAHUTE_P8 "u"
|
||||
# define CAHUTE_PRIx8 CAHUTE_P8 "x"
|
||||
# define CAHUTE_PRIX8 CAHUTE_P8 "X"
|
||||
# define CAHUTE_PRIu16 CAHUTE_P16 "u"
|
||||
# define CAHUTE_PRIx16 CAHUTE_P16 "x"
|
||||
# define CAHUTE_PRIX16 CAHUTE_P16 "X"
|
||||
# define CAHUTE_PRIu32 CAHUTE_P32 "u"
|
||||
# define CAHUTE_PRIx32 CAHUTE_P32 "x"
|
||||
# define CAHUTE_PRIX32 CAHUTE_P32 "X"
|
||||
|
||||
# endif
|
||||
|
||||
/* printf definition for `size_t`. */
|
||||
|
||||
# if defined(_WIN64)
|
||||
# define CAHUTE_PRIuSIZE "l64u"
|
||||
# define CAHUTE_PRIxSIZE "l64x"
|
||||
# define CAHUTE_PRIXSIZE "l64X"
|
||||
# elif defined(_WIN32)
|
||||
# define CAHUTE_PRIuSIZE "u"
|
||||
# define CAHUTE_PRIxSIZE "x"
|
||||
# define CAHUTE_PRIXSIZE "X"
|
||||
# else
|
||||
# define CAHUTE_PRIuSIZE "zu"
|
||||
# define CAHUTE_PRIxSIZE "zx"
|
||||
# define CAHUTE_PRIXSIZE "zX"
|
||||
# endif
|
||||
|
||||
/* ---
|
||||
* Endianess management.
|
||||
* --- */
|
||||
|
||||
CAHUTE_BEGIN_DECLS
|
||||
|
||||
CAHUTE_EXTERN(cahute_u16) cahute_be16toh OF((cahute_u16 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u16) cahute_le16toh OF((cahute_u16 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u32) cahute_be32toh OF((cahute_u32 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u32) cahute_le32toh OF((cahute_u32 cahute__x));
|
||||
|
||||
CAHUTE_EXTERN(cahute_u16) cahute_htobe16 OF((cahute_u16 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u16) cahute_htole16 OF((cahute_u16 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u32) cahute_htobe32 OF((cahute_u32 cahute__x));
|
||||
CAHUTE_EXTERN(cahute_u32) cahute_htole32 OF((cahute_u32 cahute__x));
|
||||
|
||||
CAHUTE_END_DECLS
|
||||
|
||||
/* Try to get native macros. */
|
||||
# if defined(__APPLE__)
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# define cahute_macro_be16toh(CAHUTE__X) OSSwapBigToHostInt16(CAHUTE__X)
|
||||
# define cahute_macro_le16toh(CAHUTE__X) OSSwapLittleToHostInt16(CAHUTE__X)
|
||||
# define cahute_macro_be32toh(CAHUTE__X) OSSwapBigToHostInt32(CAHUTE__X)
|
||||
# define cahute_macro_le32toh(CAHUTE__X) OSSwapLittleToHostInt32(CAHUTE__X)
|
||||
# define cahute_macro_htobe16(CAHUTE__X) OSSwapHostToBigInt16(CAHUTE__X)
|
||||
# define cahute_macro_htole16(CAHUTE__X) OSSwapHostToLittleInt16(CAHUTE__X)
|
||||
# define cahute_macro_htobe32(CAHUTE__X) OSSwapHostToBigInt32(CAHUTE__X)
|
||||
# define cahute_macro_htole32(CAHUTE__X) OSSwapHostToLittleInt32(CAHUTE__X)
|
||||
# elif defined(__OpenBSD__)
|
||||
# include <sys/endian.h>
|
||||
# define cahute_macro_be16toh(CAHUTE__X) be16toh(CAHUTE__X)
|
||||
# define cahute_macro_le16toh(CAHUTE__X) le16toh(CAHUTE__X)
|
||||
# define cahute_macro_be32toh(CAHUTE__X) be32toh(CAHUTE__X)
|
||||
# define cahute_macro_le32toh(CAHUTE__X) le32toh(CAHUTE__X)
|
||||
# define cahute_macro_htobe16(CAHUTE__X) htobe16(CAHUTE__X)
|
||||
# define cahute_macro_htole16(CAHUTE__X) htole16(CAHUTE__X)
|
||||
# define cahute_macro_htobe32(CAHUTE__X) htobe32(CAHUTE__X)
|
||||
# define cahute_macro_htole32(CAHUTE__X) htole32(CAHUTE__X)
|
||||
# elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) \
|
||||
|| defined(__WINDOWS__)
|
||||
# include <sys/param.h>
|
||||
# include <winsock2.h>
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define cahute_macro_be16toh(CAHUTE__X) ntohs(CAHUTE__X)
|
||||
# define cahute_macro_le16toh(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_be32toh(CAHUTE__X) ntohl(CAHUTE__X)
|
||||
# define cahute_macro_le32toh(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_htobe16(CAHUTE__X) htons(CAHUTE__X)
|
||||
# define cahute_macro_htole16(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_htobe32(CAHUTE__X) htonl(CAHUTE__X)
|
||||
# define cahute_macro_htole32(CAHUTE__X) (CAHUTE__X)
|
||||
# else
|
||||
# define cahute_macro_be16toh(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_le16toh(CAHUTE__X) ntohs(CAHUTE__X)
|
||||
# define cahute_macro_be32toh(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_le32toh(CAHUTE__X) ntohl(CAHUTE__X)
|
||||
# define cahute_macro_htobe16(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_htole16(CAHUTE__X) htons(CAHUTE__X)
|
||||
# define cahute_macro_htobe32(CAHUTE__X) (CAHUTE__X)
|
||||
# define cahute_macro_htole32(CAHUTE__X) htonl(CAHUTE__X)
|
||||
# endif
|
||||
# elif defined(__GLIBC__) && defined(__USE_MISC)
|
||||
# include <endian.h>
|
||||
# define cahute_macro_be16toh(CAHUTE__X) be16toh(CAHUTE__X)
|
||||
# define cahute_macro_le16toh(CAHUTE__X) le16toh(CAHUTE__X)
|
||||
# define cahute_macro_be32toh(CAHUTE__X) be32toh(CAHUTE__X)
|
||||
# define cahute_macro_le32toh(CAHUTE__X) le32toh(CAHUTE__X)
|
||||
# define cahute_macro_htobe16(CAHUTE__X) htobe16(CAHUTE__X)
|
||||
# define cahute_macro_htole16(CAHUTE__X) htole16(CAHUTE__X)
|
||||
# define cahute_macro_htobe32(CAHUTE__X) htobe32(CAHUTE__X)
|
||||
# define cahute_macro_htole32(CAHUTE__X) htole32(CAHUTE__X)
|
||||
# endif
|
||||
|
||||
/* CAHUTE_NO_ENDIAN may be defined by cdefs.c to be able to define the
|
||||
* functions prototyped above. */
|
||||
# ifndef CAHUTE_NO_ENDIAN
|
||||
# ifdef cahute_macro_be16toh
|
||||
# define cahute_be16toh(CAHUTE__X) cahute_macro_be16toh(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_le16toh
|
||||
# define cahute_le16toh(CAHUTE__X) cahute_macro_le16toh(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_be32toh
|
||||
# define cahute_be32toh(CAHUTE__X) cahute_macro_be32toh(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_le32toh
|
||||
# define cahute_le32toh(CAHUTE__X) cahute_macro_le32toh(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_htobe16
|
||||
# define cahute_htobe16(CAHUTE__X) cahute_macro_htobe16(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_htole16
|
||||
# define cahute_htole16(CAHUTE__X) cahute_macro_htole16(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_htobe32
|
||||
# define cahute_htobe32(CAHUTE__X) cahute_macro_htobe32(CAHUTE__X)
|
||||
# endif
|
||||
# ifdef cahute_macro_htole32
|
||||
# define cahute_htole32(CAHUTE__X) cahute_macro_htole32(CAHUTE__X)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
CAHUTE_END_NAMESPACE
|
||||
|
||||
#endif /* CAHUTE_CDEFS_H */
|
|
@ -0,0 +1,47 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef CAHUTE_CONFIG_H
|
||||
# define CAHUTE_CONFIG_H 1
|
||||
|
||||
# define CAHUTE_LOGLEVEL_INFO 10
|
||||
# define CAHUTE_LOGLEVEL_WARNING 20
|
||||
# define CAHUTE_LOGLEVEL_ERROR 30
|
||||
# define CAHUTE_LOGLEVEL_FATAL 40
|
||||
# define CAHUTE_LOGLEVEL_NONE 50
|
||||
|
||||
# define CAHUTE_VERSION "${PROJECT_VERSION}"
|
||||
# define CAHUTE_VERNUM ${PROJECT_VERSION_HEX}
|
||||
# define CAHUTE_MAJOR ${PROJECT_VERSION_MAJOR}
|
||||
# define CAHUTE_MINOR ${PROJECT_VERSION_MINOR}
|
||||
# define CAHUTE_DEFAULT_LOGLEVEL CAHUTE_LOGLEVEL_${DEFAULT_LOGLEVEL}
|
||||
|
||||
# define CAHUTE_URL "${PROJECT_HOMEPAGE_URL}"
|
||||
# define CAHUTE_ISSUES_URL "${PROJECT_ISSUES_URL}"
|
||||
|
||||
#endif /* CAHUTE_CONFIG_H */
|
|
@ -0,0 +1,80 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef CAHUTE_DETECTION_H
|
||||
#define CAHUTE_DETECTION_H 1
|
||||
#include "cdefs.h"
|
||||
|
||||
CAHUTE_BEGIN_NAMESPACE
|
||||
CAHUTE_DECLARE_TYPE(cahute_serial_detection_entry)
|
||||
CAHUTE_DECLARE_TYPE(cahute_usb_detection_entry)
|
||||
|
||||
struct cahute_serial_detection_entry {
|
||||
char const *cahute_serial_detection_entry_name;
|
||||
};
|
||||
|
||||
#define CAHUTE_USB_DETECTION_ENTRY_TYPE_SEVEN 1
|
||||
#define CAHUTE_USB_DETECTION_ENTRY_TYPE_SCSI 2
|
||||
|
||||
struct cahute_usb_detection_entry {
|
||||
int cahute_usb_detection_entry_bus;
|
||||
int cahute_usb_detection_entry_address;
|
||||
int cahute_usb_detection_entry_type;
|
||||
};
|
||||
|
||||
typedef int(cahute_detect_serial_entry_func)(
|
||||
void *cookie,
|
||||
cahute_serial_detection_entry const *entry
|
||||
);
|
||||
|
||||
typedef int(cahute_detect_usb_entry_func)(
|
||||
void *cookie,
|
||||
cahute_usb_detection_entry const *entry
|
||||
);
|
||||
|
||||
/* ---
|
||||
* List available devices.
|
||||
* --- */
|
||||
|
||||
CAHUTE_BEGIN_DECLS
|
||||
|
||||
CAHUTE_EXTERN(int)
|
||||
cahute_detect_serial
|
||||
OF((cahute_detect_serial_entry_func CAHUTE_NNPTR(cahute__func),
|
||||
void *cahute__cookie)) CAHUTE_NONNULL(1);
|
||||
|
||||
CAHUTE_EXTERN(int)
|
||||
cahute_detect_usb
|
||||
OF((cahute_detect_usb_entry_func CAHUTE_NNPTR(cahute__func),
|
||||
void *cahute__cookie)) CAHUTE_NONNULL(1);
|
||||
|
||||
CAHUTE_END_DECLS
|
||||
|
||||
CAHUTE_END_NAMESPACE
|
||||
|
||||
#endif /* CAHUTE_DETECTION_H */
|
|
@ -0,0 +1,52 @@
|
|||
/* ****************************************************************************
|
||||
* Copyright (C) 2024 Thomas Touhey <thomas@touhey.fr>
|
||||
*
|
||||
* This software is governed by the CeCILL 2.1 license under French law and
|
||||
* abiding by the rules of distribution of free software. You can use, modify
|
||||
* and/or redistribute the software under the terms of the CeCILL 2.1 license
|
||||
* as circulated by CEA, CNRS and INRIA at the following
|
||||
* URL: https://cecill.info
|
||||
*
|
||||
* As a counterpart to the access to the source code and rights to copy, modify
|
||||
* and redistribute granted by the license, users are provided only with a
|
||||
* limited warranty and the software's author, the holder of the economic
|
||||
* rights, and the successive licensors have only limited liability.
|
||||
*
|
||||
* In this respect, the user's attention is drawn to the risks associated with
|
||||
* loading, using, modifying and/or developing or reproducing the software by
|
||||
* the user in light of its specific status of free software, that may mean
|
||||
* that it is complicated to manipulate, and that also therefore means that it
|
||||
* is reserved for developers and experienced professionals having in-depth
|
||||
* computer knowledge. Users are therefore encouraged to load and test the
|
||||
* software's suitability as regards their requirements in conditions enabling
|
||||
* the security of their systems and/or data to be ensured and, more generally,
|
||||
* to use and operate it in the same conditions as regards security.
|
||||
*
|
||||
* The fact that you are presently reading this means that you have had
|
||||
* knowledge of the CeCILL 2.1 license and that you accept its terms.
|
||||
* ************************************************************************* */
|
||||
|
||||
#ifndef CAHUTE_ERROR_H
|
||||
#define CAHUTE_ERROR_H 1
|
||||
|
||||
CAHUTE_BEGIN_NAMESPACE
|
||||
|
||||
#define CAHUTE_OK 0x0000 /* No error has occurred. */
|
||||
#define CAHUTE_ERROR_UNKNOWN 0x0001 /* An unknown error has occurred. */
|
||||
#define CAHUTE_ERROR_IMPL 0x0002 /* A feature was unimplemented. */
|
||||
#define CAHUTE_ERROR_ALLOC 0x0003 /* A memory allocation has failed. */
|
||||
#define CAHUTE_ERROR_PRIV 0x0004 /* Insufficient privileges were found. */
|
||||
#define CAHUTE_ERROR_INT 0x0005 /* Interrupted by a callback. */
|
||||
#define CAHUTE_ERROR_SIZE 0x0006 /* Some received data was too big. */
|
||||
#define CAHUTE_ERROR_NOT_FOUND 0x0101 /* Device could not be found. */
|
||||
#define CAHUTE_ERROR_TOO_MANY 0x0102 /* Too Many Devices found. */
|
||||
#define CAHUTE_ERROR_INCOMPAT 0x0103 /* Found device is incompatible. */
|
||||
#define CAHUTE_ERROR_GONE 0x0104 /* Device is gone or I/O has failed. */
|
||||
#define CAHUTE_ERROR_TIMEOUT 0x0105 /* A timeout has occurred. */
|
||||
#define CAHUTE_ERROR_CORRUPT 0x0106 /* Corrupted packet (invalid checksum) */
|
||||
#define CAHUTE_ERROR_IRRECOV 0x0107 /* Irrecoverable link */
|
||||
#define CAHUTE_ERROR_NOOW 0x0201 /* File was not overwritten. */
|
||||
|
||||
CAHUTE_END_NAMESPACE
|
||||
|
||||
#endif /* CAHUTE_ERROR_H */
|