diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8014a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.gradle +.settings +.project +.classpath +.project +.maven +build diff --git a/bin/Debug/WiimoteLib.dll b/bin/Debug/WiimoteLib.dll deleted file mode 100644 index da8e126..0000000 Binary files a/bin/Debug/WiimoteLib.dll and /dev/null differ diff --git a/bin/Debug/WiimoteWhiteboard.exe b/bin/Debug/WiimoteWhiteboard.exe deleted file mode 100644 index 28f2c9f..0000000 Binary files a/bin/Debug/WiimoteWhiteboard.exe and /dev/null differ diff --git a/bin/Debug/wiimotelibpoll.exe b/bin/Debug/wiimotelibpoll.exe deleted file mode 100644 index 72937a2..0000000 Binary files a/bin/Debug/wiimotelibpoll.exe and /dev/null differ diff --git a/bin/Debug/wiiscan.exe b/bin/Debug/wiiscan.exe deleted file mode 100644 index 3b0f862..0000000 Binary files a/bin/Debug/wiiscan.exe and /dev/null differ diff --git a/bin/Debug/wiiscan.ini b/bin/Debug/wiiscan.ini deleted file mode 100644 index e2c842f..0000000 --- a/bin/Debug/wiiscan.ini +++ /dev/null @@ -1,82 +0,0 @@ -% Configfile_begin - % config file for wiiscan - - % all usb device ids, not used yet in the scanning - all_usb_hubs="" - - % single power controlling usb hub, only nessesary when powerering over usb, for automatic resetting. If not used, put "" - % active_usb_hub="@PCI\VEN_8086&DEV_2934&SUBSYS_20F017AA&REV_03\3&B1BFB68&0&E8" - active_usb_hub="" - - % a list of allowed wiimotes in the form xx:xx:xx:xx:xx:xx, wildcard match is 00:00:00:00:00:00 - allowed_wiimote_adr=00:00:00:00:00:00 - % my set of wiimotes - %allowed_wiimote_adr=00:19:?D:??:6?:?? 00:1F:C5:??:??:?? - - % launching exe file have a problem with spaces, hence renamed exe, replaced space with underscores - % The original Johnny Chung Lee wb software version 0.3, downloaded from [http://johnnylee.net/projects/wii/] - %whiteboard_software="d:/WiimoteWhiteboard/WiimoteWhiteboard_v0.3.exe" - - % same stuff, but binary build from sources and redistributed in this package - %whiteboard_software="WiimoteWhiteboard.exe" - - % and finally, a custom build v0.3 version, with fixed calibration.dat write - whiteboard_software=WiimoteWhiteboard_v0.3.exe - - % Boon Jin's wb software version 0.6 - %whiteboard_software="d:/wsb/WiimoteSmoothboard.exe" - - % wiiscan parameters - %option_device="Nintendo RVL-CNT-01" - - % number of bt scanning attempts in a autoscan, timout is increased for every scan as retryattempt*option_timeout - %option_scanretries=3 - - % long time (4000 and above, or increase option_scanretries) when matching name, short (1000-2000) when matching address - option_timeout=4000 - - % wiimote scanning time, only applicable used for wiilib - option_wiitimeout=1000 - - % delay bewteen powerdown/up, see man for details - option_usbsleep=1000 - option_usbmsleep=1000 - %option_btsleep=2000 - - % output verbose flag, 0 or 1 - option_debug=1 - - % start wb at successfull connect, 0 or 1 - option_startwhiteboard=1 - - % logging output file, typical wiiscan_log.txt , put nothing if no logging is wanted - option_logfile=wiiscan_log.txt - - % wiimote connection library, use none, wiiuse, or wiimotelib - option_wiilib=wiimotelib - - % 0=no power cycle, 1=USB hub control, 2=USBm IO, 3=USB Devcon - option_usbpowermode=3 - - % 0=remove if not connectable, 1=always remove, 2=never remove - %option_forceremove=0 - - % bt radio to use, not working yet - %option_btradio=00:50:B6:A0:48:8C - - % wiiscantray options - % number of connection attempts before autoscan i restarted - option_tray_pool_retries=2 - - % retry sleep, keep it low (<1000) to catch an open connection - option_tray_sleep_between_pool_retries=250 - - % sleep bewteen polls, when wiimote is succeful connected, keep it hight (>2000) to avoid to much CPU usage - option_tray_sleep_between_pool_loops=1000 - - % final connection step reqires some sleep before windows PnP is ready - option_sleep_before_final_connect=1500 - - % delay after launch of wb software, keep it at a medium value (2000-10000) - option_sleep_after_startwhiteboard=4000 -% Configfile_end diff --git a/bin/Debug/wiiscantray.exe b/bin/Debug/wiiscantray.exe deleted file mode 100644 index 62ef3b8..0000000 Binary files a/bin/Debug/wiiscantray.exe and /dev/null differ diff --git a/bin/Debug/DelcomDLL.dll b/bin/DelcomDLL.dll similarity index 100% rename from bin/Debug/DelcomDLL.dll rename to bin/DelcomDLL.dll diff --git a/bin/Release/DelcomDLL.dll b/bin/Release/DelcomDLL.dll deleted file mode 100644 index ecfa470..0000000 Binary files a/bin/Release/DelcomDLL.dll and /dev/null differ diff --git a/bin/Release/USBm.dll b/bin/Release/USBm.dll deleted file mode 100644 index 1460ff3..0000000 Binary files a/bin/Release/USBm.dll and /dev/null differ diff --git a/bin/Release/WiimoteWhiteboard_v0.3.exe b/bin/Release/WiimoteWhiteboard_v0.3.exe deleted file mode 100644 index 9edbc31..0000000 Binary files a/bin/Release/WiimoteWhiteboard_v0.3.exe and /dev/null differ diff --git a/bin/Release/wiiuse.dll b/bin/Release/wiiuse.dll deleted file mode 100644 index a7e228c..0000000 Binary files a/bin/Release/wiiuse.dll and /dev/null differ diff --git a/bin/Debug/USBm.dll b/bin/USBm.dll similarity index 100% rename from bin/Debug/USBm.dll rename to bin/USBm.dll diff --git a/bin/Release/WiimoteLib.dll b/bin/WiimoteLib.dll similarity index 100% rename from bin/Release/WiimoteLib.dll rename to bin/WiimoteLib.dll diff --git a/bin/Release/WiimoteWhiteboard.exe b/bin/WiimoteWhiteboard.exe similarity index 100% rename from bin/Release/WiimoteWhiteboard.exe rename to bin/WiimoteWhiteboard.exe diff --git a/bin/Debug/WiimoteWhiteboard_v0.3.exe b/bin/WiimoteWhiteboard_v0.3.exe similarity index 100% rename from bin/Debug/WiimoteWhiteboard_v0.3.exe rename to bin/WiimoteWhiteboard_v0.3.exe diff --git a/bin/Release/wiimotelibpoll.exe b/bin/wiimotelibpoll.exe similarity index 100% rename from bin/Release/wiimotelibpoll.exe rename to bin/wiimotelibpoll.exe diff --git a/bin/Release/wiiscan.exe b/bin/wiiscan.exe similarity index 100% rename from bin/Release/wiiscan.exe rename to bin/wiiscan.exe diff --git a/bin/Release/wiiscan.ini b/bin/wiiscan.ini similarity index 100% rename from bin/Release/wiiscan.ini rename to bin/wiiscan.ini diff --git a/bin/Release/wiiscantray.exe b/bin/wiiscantray.exe similarity index 100% rename from bin/Release/wiiscantray.exe rename to bin/wiiscantray.exe diff --git a/bin/Debug/wiiuse.dll b/bin/wiiuse.dll similarity index 100% rename from bin/Debug/wiiuse.dll rename to bin/wiiuse.dll diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..3bcf8ce --- /dev/null +++ b/build.gradle @@ -0,0 +1,140 @@ +apply plugin: 'java' +apply plugin: 'cpp' +apply plugin: 'maven' +apply plugin: 'eclipse' + +repositories { + maven { + url 'https://github.com/Boukefalos/jlibloader/raw/mvn-repo/' + } + mavenCentral() +} + +dependencies { + compile 'com.github.boukefalos:jlibloader:0.2' + testCompile 'junit:junit:4.11' +} + +group = 'com.github.boukefalos' +project.archivesBaseName = 'wiiscan' +version = '0.9' + +task wrapper(type: Wrapper) { + gradleVersion = '1.12' +} + +model { + platforms { + windows_i386 { + architecture 'i386' + operatingSystem 'windows' + } + windows_amd64 { + architecture 'amd64' + operatingSystem 'windows' + } + } + toolChains { + gcc(Gcc) { + addPlatformConfiguration(new TargetPlatformConfiguration() { + boolean supportsPlatform(Platform platform) { + platform.operatingSystem.current && platform.operatingSystem.name == 'windows' && + platform.architecture.name == 'amd64' + } + List getCppCompilerArgs() { ['-m64', '-fpermissive'] } + List getCCompilerArgs() { ['-m64'] } + List getObjectiveCCompilerArgs() { ['-m64'] } + List getObjectiveCppCompilerArgs() { ['-m64'] } + List getAssemblerArgs() { ['--64'] } + List getLinkerArgs() { ['-m64'] } + List getStaticLibraryArchiverArgs() { [] } + }) + } + } + repositories { + libs(PrebuiltLibraries) { + usb { lib -> + binaries.withType(StaticLibraryBinary) { + staticLibraryFile = file("lib/${targetPlatform.name}/libusb-1.0.dll") + } + } + } + } +} + +libraries { + main { + baseName project.archivesBaseName + } + all { + binaries.all { + linker.args '-Wl,--kill-at', '-static-libgcc', '-static-libstdc++' + // lib library: 'usb', linkage: 'static' + } + } +} + +tasks.withType(Upload) { + repositories { + mavenDeployer { + repository(url: uri('.maven')) + } + } +} + +configurations { + jni +} + +def deployer = uploadJni.repositories.mavenDeployer + +binaries.withType(SharedLibraryBinary) { binary -> + if (!buildable) { + return + } + def variantName = "${targetPlatform.operatingSystem.name}-${targetPlatform.architecture.name}" + def taskName = "jar-${variantName}" + def nativeJar = project.tasks.findByName(taskName) + if (nativeJar == null) { + nativeJar = project.task(taskName, type: Jar) { + baseName = "${project.archivesBaseName}-$variantName" + } + artifacts { + jni nativeJar + } + def jniPom = deployer.addFilter(variantName) { artifact, file -> + return file == nativeJar.archivePath + } + jniPom.groupId = project.group + jniPom.artifactId = nativeJar.baseName + jniPom.version = version + jniPom.scopeMappings.mappings.clear() + } + def builderTask = binary.tasks.builder + def libraryDirectory = project.group.replace('.', '/') + "/${project.archivesBaseName}/${variantName}" + nativeJar.into(libraryDirectory) { + from builderTask.outputFile + from file("lib/${targetPlatform.name}/libusb0.dll") + } + // nativeJar.dependsOn builderTask +} + +def mainPom = uploadArchives.repositories.mavenDeployer.pom +mainPom.groupId = project.group +mainPom.artifactId = jar.baseName +mainPom.version = project.version +mainPom.scopeMappings.mappings.clear() +mainPom.withXml { provider -> + def node = provider.asNode() + def deps = node.appendNode('dependencies') + ['windows-amd64', 'windows-i386'].each { platform -> + def dep = deps.appendNode('dependency') + dep.appendNode('groupId', project.group) + dep.appendNode('artifactId', "${project.archivesBaseName}-${platform}") + dep.appendNode('version', jniVersion) + } + def dep = deps.appendNode('dependency') + dep.appendNode('groupId', 'com.github.boukefalos') + dep.appendNode('artifactId', 'jlibloader') + dep.appendNode('version', '0.3') +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..0087cd3 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..c821e11 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Jul 10 22:54:12 BST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/cpp/wiiscan.cpp b/src/main/cpp/wiiscan.cpp new file mode 100644 index 0000000..c44caef --- /dev/null +++ b/src/main/cpp/wiiscan.cpp @@ -0,0 +1,27 @@ +// Copyright © 2009 MergeIt, Aps. +// +// License LGPLv3+: GNU lesser LGPL version 3 or later . +// This is free software: you are free to change and redistribute it. +// There is NO WARRANTY, to the extent permitted by law. +// +// This file is part of wiiscan. +// +// wiiscan is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// wiiscan is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with wiiscan. If not, see . + +#include "wiiscan.h" + +int main(int argc,char** argv) +{ + return Wiiscan::main(argc,argv); +} \ No newline at end of file diff --git a/src/main/headers/DelcomDLL.h b/src/main/headers/DelcomDLL.h new file mode 100644 index 0000000..8fd16b5 --- /dev/null +++ b/src/main/headers/DelcomDLL.h @@ -0,0 +1,128 @@ +// Delcom Engineering +// DelcomDLL.h +// Version 0.6 +// 02/11/07 + +#ifndef DELCOMDLL_HEADER +#define DELCOMDLL_HEADER 1 + + +// defines +#define OFF 0 +#define ON 1 +#define FLASH 2 + +#define USBIODS 1 +#define USBDELVI 2 +#define USBNDSPY 3 + +#define GREENLED 0 +#define REDLED 1 +#define BLUELED 2 + +#define MaxDeviceLen 512 + +// Typedef +typedef struct _DeviceNameStruct{ + char DeviceName[MaxDeviceLen]; +} DeviceNameStruct, *pDeviceNameStruct; + + +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef char CHAR; +typedef unsigned short WORD; +typedef void * HANDLE; +typedef CHAR *LPSTR, *PSTR; +typedef unsigned char uchar; +typedef unsigned int uint; + +typedef struct _PacketStruct{ + uchar Recipient; + uchar DeviceModel; + uchar MajorCmd; + uchar MinorCmd; + uchar DataLSB; + uchar DataMSB; + short Length; + uchar ExtData[8]; + } PacketStruct,*pPacketStruct; + + + + +// DLL Generic Functions +HANDLE DelcomGetDLLHandle(void); +double __stdcall DelcomGetDLLVersion(void); +DWORD __stdcall DelcomGetDLLDate(LPSTR); +DWORD __stdcall DelcomVerboseControl( DWORD Mode, LPSTR Header ); + +DWORD __stdcall DelcomGetNthDevice(DWORD, DWORD, LPSTR); +DWORD __stdcall DelcomScanDevices( DWORD, DeviceNameStruct[], DWORD ); +HANDLE __stdcall DelcomOpenDevice( LPSTR, DWORD); +DWORD __stdcall DelcomCloseDevice(HANDLE); +DWORD __stdcall DelcomGetDeviceCount( DWORD Type ); + +DWORD __stdcall DelcomReadDeviceVersion(HANDLE ); +DWORD __stdcall DelcomReadDeviceSerialNum(LPSTR, HANDLE ); +DWORD __stdcall DelcomSendPacket( HANDLE, pPacketStruct, pPacketStruct); + + +// USBDELVI - Visual Indicator Functions +DWORD __stdcall DelcomLEDControl( HANDLE hFile, DWORD Color, DWORD Mode ); +DWORD __stdcall DelcomEnableAutoConfirm(HANDLE hUsb, DWORD Mode); +DWORD __stdcall DelcomEnableAutoClear(HANDLE hUsb, DWORD Mode); +DWORD __stdcall DelcomBuzzer(HANDLE hUsb, uchar Mode, uchar Freq, uchar Repeat, uchar OnTime, uchar OffTime); +DWORD __stdcall DelcomLoadInitialPhaseDelay(HANDLE hUsb, BYTE Color, BYTE Delay); +DWORD __stdcall DelcomSyncLeds(HANDLE hUsb); +DWORD __stdcall DelcomLoadPreScalar(HANDLE hUsb, BYTE PreScalar); +DWORD __stdcall DelcomLoadLedFreqDuty(HANDLE hUsb, BYTE Color, BYTE Low, BYTE High); +DWORD __stdcall DelcomGetButtonStatus(HANDLE hUsb ); +DWORD __stdcall DelcomReadVersionNumber(HANDLE hUsb ); +DWORD __stdcall DelcomReadSerialNumber(HANDLE hUsb ); +DWORD __stdcall DelcomLEDPower( HANDLE hUsb, DWORD Color, DWORD Power ); + + + +// USBIODS - USB IO Functions +DWORD __stdcall DelcomWritePortPin(HANDLE hUsb, BYTE Port, BYTE Pin, BYTE Value ); +DWORD __stdcall DelcomWritePorts(HANDLE hUsb, BYTE Port0, BYTE Port1 ); +DWORD __stdcall DelcomReadPorts(HANDLE hUsb, BYTE* Port0, BYTE* Port1 ); + +DWORD __stdcall DelcomWrite64Bit(HANDLE hUsb, LPSTR DataExt ); +DWORD __stdcall DelcomRead64Bit(HANDLE hUsb, LPSTR DataExt ); + +DWORD __stdcall DelcomWriteI2C(HANDLE hUsb, BYTE CmdAdd, BYTE Length, LPSTR DataExt ); +DWORD __stdcall DelcomReadI2C(HANDLE hUsb, BYTE CmdAdd, BYTE Length, LPSTR DataExt ); +DWORD __stdcall DelcomSelReadI2C(HANDLE hUsb, BYTE SetAddCmd, BYTE Address, BYTE ReadCmd, BYTE Length, LPSTR DataExt ); +DWORD __stdcall DelcomWriteI2CEEPROM(HANDLE hUsb, DWORD Address, DWORD Length, BYTE CtrlCode, BYTE WriteDelay, LPSTR pData ); +DWORD __stdcall DelcomReadI2CEEPROM(HANDLE hUsb, DWORD Address, DWORD Length, BYTE CtrlCode, LPSTR pData ); + + +DWORD __stdcall DelcomRS232Ctrl(HANDLE hUsb, DWORD Mode, DWORD Value ); +DWORD __stdcall DelcomWriteRS232(HANDLE hUsb, DWORD Length, LPSTR DataExt ); +DWORD __stdcall DelcomReadRS232(HANDLE hUsb, LPSTR DataExt ); + + // SPI Commands +DWORD __stdcall DelcomSPIWrite( HANDLE hUsb, DWORD ClockCount, LPSTR pData); +DWORD __stdcall DelcomSPISetClock( HANDLE hUsb, DWORD ClockPeriod ); +DWORD __stdcall DelcomSPIRead(HANDLE hUsb, LPSTR pData); +DWORD __stdcall DelcomSPIWr8Read64( HANDLE hUsb, DWORD WrData, DWORD ClockCount, LPSTR pData); + + + +// USBNDSPY Functions +DWORD __stdcall DelcomNumericMode(HANDLE hUsb, BYTE Mode, BYTE Rate ); +DWORD __stdcall DelcomNumericScanRate(HANDLE hUsb, BYTE ScanRate ); +DWORD __stdcall DelcomNumericSetup(HANDLE hUsb, BYTE Digits ); +DWORD __stdcall DelcomNumericRaw(HANDLE hUsb, LPSTR Str ); +DWORD __stdcall DelcomNumericInteger(HANDLE hUsb, DWORD Number, DWORD Base ); +DWORD __stdcall DelcomNumericHexaDecimal(HANDLE hUsb, DWORD Number, DWORD Base ); +DWORD __stdcall DelcomNumericDouble(HANDLE hUsb, double Number, DWORD Base ); + + +#endif + + + diff --git a/src/main/headers/args.h b/src/main/headers/args.h new file mode 100644 index 0000000..21ae941 --- /dev/null +++ b/src/main/headers/args.h @@ -0,0 +1,143 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __ARGS_H__ +#define __ARGS_H__ + +class args{ + private: + typedef vector t_args; + t_args m_args; + + void Remove(t_args::iterator itt1,int n) + { + t_args args2; + for(t_args::iterator itt2=m_args.begin();itt2!=m_args.end();++itt2) { + if(itt2!=itt1) args2.push_back(*itt2); + else {if (--n>0) ++itt1;} + } + m_args=args2; + } + + t_args::iterator Find(const string& v) + { + for(t_args::iterator itt=m_args.begin();itt!=m_args.end();++itt) { + if (v==*itt) return itt; + } + return m_args.end(); + } + + t_args::const_iterator Find(const string& v) const + { + for(t_args::const_iterator itt=m_args.begin();itt!=m_args.end();++itt) { + if (v==*itt) return itt; + } + return m_args.end(); + } + + public: + args(const int argc,char **argv,const bool printargs=false) + { + for(int i=0;i=size()) throw_("argument[] out of range"); + return m_args[i]; + } + + size_t size() const {return m_args.size();} + bool hasopt(const string& tag) const {return Find(tag)!=m_args.end();} + template T Totype(const size_t i) const {return totype((*this)[i]);} + template T Tounit(const size_t i) const { + const string& s=(*this)[i+1]; + #ifndef USE_UNITS + // fake test of units, primitive test, must be one-of: kpc, per_kpc and msun1E10 + if (s!="kpc/h" && s!="h/kpc" && s!="msun1E10/h") throw_("bad unit=<" + s + ">, can only handle units of type: kpc/h, h/kpc, and msun1E10/h"); + #endif + return totype((*this)[i] + " " + s); + } + + template + T parseval(const string& tag,const T& defaultval) + { + t_args::iterator itt=Find(tag); + if (itt==m_args.end() || itt+1==m_args.end()) return defaultval; + + const T v=totype(*(++itt)); + Remove(--itt,2); + + return v; + } + + template + pair parseval(const string& tag,const T& defaultval1,const R& defaultval2) + { + t_args::iterator itt=Find(tag); + if (itt==m_args.end() || itt+1==m_args.end() || itt+2==m_args.end()) return make_pair(defaultval1,defaultval2); + + const T v1=totype(*(++itt)); + const R v2=totype(*(++itt)); + Remove(----itt,3); + + return make_pair(v1,v2); + } + + template + T parseunit(const string& tag,const T& defaultval) + { + t_args::iterator itt=Find(tag); + if (itt==m_args.end() || itt+2==m_args.end()) return defaultval; + + const string s1=*(++itt); + const string s2=*(++itt); + const T v=totype(s1 + " " + s2); + Remove(----itt,3); + + return v; + } + + bool parseopt(const string& tag) + { + t_args::iterator itt=Find(tag); + if (itt==m_args.end()) return false; + Remove(itt,1); + + return true; + } + + int getoptindex(const string& tag) const + { + int n=0; + for(t_args::const_iterator itt=m_args.begin();itt!=m_args.end();++itt,++n) { + if (tag==*itt) { + assert( n>=0 && size_t(n)m_args.size() || i+n>m_args.size()) throw_("out of range"); + m_args.erase(m_args.begin()+i,m_args.begin()+i+n); + } + + friend ostream& operator<<(ostream& s,const args& v) + { + for(t_args::const_iterator itt=v.m_args.begin();itt!=v.m_args.end();++itt){ + s << *itt << " "; + } + return s; + } +}; + +#endif // __ARGS_H__ diff --git a/src/main/headers/configfile.h b/src/main/headers/configfile.h new file mode 100644 index 0000000..574d738 --- /dev/null +++ b/src/main/headers/configfile.h @@ -0,0 +1,143 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __CONFIGFILE_H__ +#define __CONFIGFILE_H__ + +class Configfile { + private: + typedef vector t_value; + t_value m_text; + map m_vals; + string m_rem; + string m_strip; + string m_file; + + void Load(istream &s) + { + if (!s) throw_("bad stream in configfile input operator"); + char buff[32*1024]; + bool ini=true; + while(s.getline(buff,32*1024)) { + const string b(strip(buff)); + if (ini && b!=m_rem + " Configfile_begin") throw_("bad stream in configfile input operator, missing begin tag"); + if (b==m_rem + " Configfile_end") return; + const string t(strip(removerems(b,m_rem))); + if (t.size()>0){ + m_text.push_back(t); + const size_t n=t.find_first_of("="); + istringstream s2(t.substr(0,n) + " " + (n==string::npos ? "" : t.substr(n+1))); + string v,k; + s2 >> k; + while ((s2 >> v)) m_vals[k].push_back(v); + } + ini=false; + } + throw_("bad stream in configfile input operator, missing end tag"); + } + + string Strip(const string& s) const + { + for(size_t i=0;i does not exist"); + Load(s); + } + + Configfile(istream& s,const string rem="%") : m_rem(rem) + { + if (!s) throw_("stream is invalid"); + Load(s); + } + + size_t size() const {return m_text.size();} + const string& operator[](const size_t n) const {assert(n::const_iterator itt=m_vals.find(key); return itt!=m_vals.end();} + void Save(const string& filename) {ofstream s(filename.c_str()); s << *this;} + + bool operator==(const Configfile& c) const + { + if (m_text!=c.m_text) return false; + else if (m_vals!=c.m_vals) return false; + else if (m_rem!=c.m_rem) return false; + else if (m_strip!=c.m_strip) return false; + else if (m_file!=c.m_file) return false; + return true; + } + bool operator!=(const Configfile& c) const {return !this->operator==(c);} + + void Checkfilechange() + { + if (m_file.empty()) return; + Configfile c(m_file); + if (c!=*this) *this=c; + } + + const t_value& Get(const string& key) const + { + map::const_iterator itt=m_vals.find(key); + if (itt==m_vals.end()) throw_("No such entry, <" + key + ">, in configfile"); + return itt->second; + } + + template const T Get(const string& key,const bool fullline=false) const + { + const t_value& v=Get(key); + assert( v.size()>0 ); + string s=v[0]; + if (fullline) for(size_t i=1;i(s); + return t; + } + + template const T Initialize(const string& key,const T valiueifnotfound,const bool fullline=false) const + { + if (!hasEntry(key)) return valiueifnotfound; + else return Get(key,fullline); + } + + template + pair GetConfig(const string& e) const + { + if (!hasEntry(e)) return make_pair(false,T()); + else return make_pair(true,Get(e,true)); + } + + template void Set(const string& key,const T& v) + { + t_value val; + val.push_back(tostring(v)); + m_vals[key]=val; + m_text.push_back(key + " " + val[0]); + } + + friend ostream& operator<<(ostream& s,const Configfile& x) + { + s << x.m_rem << " Configfile_begin\n"; + for(map::const_iterator itt1=x.m_vals.begin();itt1!=x.m_vals.end();++itt1){ + s << "\t" << itt1->first << " = "; + for(t_value::const_iterator itt2=itt1->second.begin();itt2!=itt1->second.end();++itt2) s << *itt2 << " "; + s << "\n"; + } + s << x.m_rem << " Configfile_end\n"; + // if (!s) throw_("bad stream in configfile output operator");, XXX throws in cout!? + return s; + } + + friend istream& operator>>(istream& s,Configfile& x){x.Load(s); return s;} +}; +#endif // __CONFIGFILE_H__ diff --git a/src/main/headers/exception.h b/src/main/headers/exception.h new file mode 100644 index 0000000..5721a37 --- /dev/null +++ b/src/main/headers/exception.h @@ -0,0 +1,197 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +// forward defs to funs.h +string Getlocaltime(); +size_t GetThreadId(); +int Message(const string& title,const string& msg,const int type=0); + +// simple class for debugging call stack +#ifdef _DEBUG + struct Stackinfo : public vector { + friend ostream& operator<<(ostream& s,const Stackinfo& x) + { + s << "Function stack {" << endl; + for(int i=x.size();i>0;--i){ + const string& f=x[i-1]; + s << " [" << i-1 << "]: " << f << "(...)" << endl; + } + return s << "}" << endl; + } + }; + + class Funstack { + private: + const string m_f; + static map m_s; + + Funstack(const Funstack&); + void operator=(const Funstack&); + + public: + Funstack(const string& f,const int line,const string& file) : m_f(f) {m_s[GetThreadId()].push_back(f);} + ~Funstack() + { + const size_t tid=GetThreadId(); + assert(m_s.find(tid)!=m_s.end()); + assert(m_s[tid].size()>0 && m_s[tid].back()==m_f); + m_s[tid].pop_back(); + } + + static const Stackinfo GetStack() + { + const size_t tid=GetThreadId(); + if (m_s.find(tid)==m_s.end()) return Stackinfo(); + else return m_s[tid]; + } + }; + map Funstack::m_s; // initialize static var + #define FUNSTACK Funstack __f_stack__(__FUNCTION__,__LINE__,__FILE__) +#else + #define FUNSTACK + #define DUMPSTACK(s) + struct Stackinfo { + friend ostream& operator<<(ostream& s,const Stackinfo& x) {return s;} + }; + class Funstack { + public: + static Stackinfo GetStack() {return Stackinfo();} + }; +#endif + +// tee like logger class +class Logger +{ +private: + //ostream* m_log; + string m_logfilename; + ofstream m_logfile; + ostream* m_log; + const bool m_logstdout,m_logstderr; + + Logger(const Logger&); + void operator=(const Logger&); + +public: + Logger(ostream* log,const bool logstdout=true,const bool logstderr=false) : m_log(log), m_logstdout(logstdout), m_logstderr(logstderr) {} + + void operator=(ostream* log){m_logfilename=""; m_logfile.close(); m_log=log;} + void open(const string& logfilename,const ios_base::openmode mode) + { + m_log=0; + if (m_logfile.is_open()) m_logfile.close(); + m_logfilename=logfilename; + m_logfile.open(m_logfilename.c_str(),mode); + if (!m_logfile) throw("cannot write to logfile <" + logfilename + ">"); // Exception uses logger class, so do not throw a nice Exception class here, use a plain throw + m_log=&m_logfile; + } + + void clear() + { + if (m_logfile.is_open()) m_logfile.close(); + m_logfile.open(m_logfilename.c_str()); + } + + template + friend Logger& operator<<(Logger& log,const T& t) + { + if(log.m_logstdout) cout << t; + if(log.m_logstderr) cerr << t; + if(log.m_log!=0) (*(log.m_log)) << t; + return log; + } + + // handle endl and like + friend Logger& operator<<(Logger& log,std::ostream& (*fn)(std::ostream&)) + { + if(log.m_logstdout) fn(cout); + if(log.m_logstderr) fn(cerr); + if(log.m_log!=0) fn(*(log.m_log)); + return log; + } + + void writelogheader(const string& msg) + { + if(m_log==0) return; + else{ + (*m_log) << "********************************************************" << endl; + (*m_log) << "** Logentry: " << msg << endl; + (*m_log) << "** Time: " << Getlocaltime(); + (*m_log) << "********************************************************" << endl; + } + } +}; + +// static global logging, default standand out +static Logger g_log(0,true,false); + +class Exception{ +private: + const string m_msg; + const string m_file; + const int m_line; + const Stackinfo m_stack; + +public: + Exception(const string msg,const string file,const int line,const Stackinfo s) : m_msg(msg), m_file(file), m_line(line), m_stack(s) {} + Exception(const char* msg,const string file,const int line,const Stackinfo s) : m_msg(msg), m_file(file), m_line(line), m_stack(s) {} + + inline static string FormatCompilerMsg(const string& file,const int line,const bool warnonly=false) + { + #ifdef WIN32 + return file + "(" + Exception::tostring(line) + ") : " + (warnonly ? "warning : " : "error : "); + #else + return file + ":" + Exception::tostring(line) + ": " + (warnonly ? "warning: " : "error: "); + #endif + } + + inline static void throw_fun(const string& msg,const string& file,const int line) + { + const string msg2=Exception::FormatCompilerMsg(file,line) + "throwing exception: " + msg; + g_log << msg2; + #ifdef _WINDOWS_ + const string f=tostring(Funstack::GetStack()); + const string msg3=msg2 + (f.size()>0 ? "\n\n" : "") + f.substr(0,300) + (f.size()>300 ? "\n..." : ""); + Message("Exception encountered...",msg3,0); + #endif + throw Exception(msg,file,line,Funstack::GetStack()); + } + + inline string Msg() const + { + return FormatCompilerMsg(m_file,m_line) + "Exception: " + m_msg; + } + + friend ostream& operator<<(ostream& os,const Exception& e) + { + return os << e.Msg() << endl << e.m_stack; + } + + template + static string tostring(const T& x) + { + ostringstream os; + os << x; + return os.str(); + } +}; + +#define throw_(msg) Exception::throw_fun(msg,__FILE__, __LINE__) +#define warn_(msg) cerr << Exception::FormatCompilerMsg(__FILE__, __LINE__,true) << msg << endl; + +#define CATCH_ALL\ + catch(const char* s) {cout.flush(); cerr << Exception::FormatCompilerMsg(__FILE__, __LINE__) << "caught exception chars: " << s;}\ + catch(const string& s) {cout.flush(); cerr << Exception::FormatCompilerMsg(__FILE__, __LINE__) << "caught exception string: " << s;}\ + catch(const Exception& s){cout.flush(); cerr << Exception::FormatCompilerMsg(__FILE__, __LINE__) << "caught Exception class: " << s;}\ + catch(...) {cout.flush(); cerr << Exception::FormatCompilerMsg(__FILE__, __LINE__) << "caught unknown exception";}\ + cerr << "...aborting" << endl; + +#endif // __EXCEPTION_H__ diff --git a/src/main/headers/file.h b/src/main/headers/file.h new file mode 100644 index 0000000..915f6ed --- /dev/null +++ b/src/main/headers/file.h @@ -0,0 +1,208 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __FILE_H__ +#define __FILE_H__ + +inline bool FileExists(const std::string& f) +{ + ifstream s(f.c_str()); + return (!s)==false; +} + +inline void AssertFileExists(const std::string& f) +{ + if (!FileExists(f)) throw_("File <" + f + "> does not exist"); +} + +inline size_t FileSize(const std::string& f) +{ + AssertFileExists(f); + ifstream s(f.c_str()); + if (!s) throw_("Stream is bad (file <" + f + ">)"); + s.seekg(0,ios::end); + if (!s) throw_("Stream is bad (file <" + f + ">)"); + return s.tellg(); +} + +inline void AssertFileNotEmpty(const std::string& f) +{ + if (FileSize(f)==0) throw_("File <" + f + "> is empty"); +} + +inline size_t FileTime(const string& file) +{ + AssertFileExists(file); + const string t=System("date -r " + file + " +%s",true,true); // seconds since 1970-01-01 00:00:00 UTC + return totype(t); + // #include + // #include + // struct stat s; + // int n=stat(file.c_str(),&s); + // if (n!=0) throw_("cannot stat file <" + file + ">"); + // assert( sizeof(time_t)==sizeof(size_t) ); + // return s.st_mtime; +} + +inline bool isFileNewer(const string& file0,const string& file1) +{ + return FileTime(file0)>FileTime(file1); +} + +inline bool DirExists(const std::string& f) +{ + const string file=f + "/.dummy.txt"; + ofstream s(file.c_str()); + if(!s) return false; + s << "testfile"; + if(!s) return false; + s.close(); + return FileSize(file)==8; +} + +inline string MakeSuffix(const int n) +{ + assert(n>=0); + if (n<=9) return "00" + tostring(n); + else if (n<=99) return "0" + tostring(n); + else return tostring(n); +} + +template +void Readdata(const string& tok,istream& is,T& t) +{ + if (!is) throw_("Stream is bad"); + is >> t; + if (!is) throw_("Reading {" + tok + "} settings"); +} + +inline string Readline(istream& is) +{ + char buff[16*1024]; + is.getline(buff,16*1024); + return string(buff); +} + +template +inline T Readtyp(ifstream& s){ + T x; + s.read(reinterpret_cast(&x),sizeof(x)); + if(!s) throw_("bad stream"); + return x; +} + +inline string Readstring(ifstream& s){ + char c=0; + string t; + do{ + c=Readtyp(s); + if(c!=0) t+=c; + } + while (c!=0); + return t; +} + +template +inline vector Readbin(std::ifstream& s,const int size) +{ + if(!s) throw_("bad stream"); + vector x(size); + s.read(reinterpret_cast(&x.front()),x.size()*sizeof(T)); + if(!s) throw_( "bad write"); + return x; +} + +template +inline void Writetyp(ofstream& s,const T& x){ + s.write(reinterpret_cast(&x),sizeof(x)); + if(!s) throw_( "bad stream"); +} + +template +inline void Writebin(std::ofstream& s,const std::vector& x,const bool writetag) +{ + if(!s) throw_("bad stream"); + const size_t sz=x.size()*sizeof(T); + if(writetag){ + Writetyp(s,sz); + } + if(!s) throw_( "bad stream" ); + s.write(reinterpret_cast(&x.front()),sz); + if(!s) throw_( "bad write"); + if (writetag) Writetyp(s,sz); + if(!s) throw_( "bad stream"); +} + +template +inline void Writebin(std::ofstream& s,const std::map& x,const bool writetag) +{ + vector t; + vector r; + t.reserve(x.size()); + r.reserve(x.size()); + for(typename std::map::const_iterator itt=x.begin();itt!=x.end();++itt){ + t.push_back(itt->first); + r.push_back(itt->second); + } + if (writetag) { + Writetyp(s,x.size()); + Writetyp(s,static_cast(sizeof(T))); + Writetyp(s,static_cast(sizeof(R))); + } + Writebin(s,t,writetag); + Writebin(s,r,writetag); +} + +template +inline void Readbin(std::ifstream& s,vector& x) +{ + if(!s) throw_("bad stream"); + const size_t sz=Readtyp(s); + if(!s) throw_( "bad stream" ); + if(sz%sizeof(T)!=0) throw_("bad size tag"); + x.resize(sz/sizeof(T)); + s.read(reinterpret_cast(&x.front()),sz); + if(!s) throw_( "bad write"); + if (Readtyp(s)!=sz) throw_("bad size tag"); + if(!s) throw_( "bad stream"); +} + +template +inline void Readbin(std::ifstream& s,map& x) +{ + vector t; + vector r; + + const size_t sz=Readtyp(s); + const size_t szT=Readtyp(s); + const size_t szR=Readtyp(s); + + if (szT!=sizeof(T)) throw_("type T size mismatch in Readbin (map)"); + if (szR!=sizeof(R)) throw_("type R size mismatch in Readbin (map)"); + + Readbin(s,t); + Readbin(s,r); + if (t.size()!=r.size()) throw_("size mismatch in Readbin (map)"); + x.clear(); + for(size_t i=0;i +inline void Writeascii(const string& filename,const std::vector& x,const string& comment="",const char& newline='\n') +{ + ofstream s(filename.c_str()); + if(!s) throw_("bad file <" + filename + ">"); + s << "% Writeascii: size=" << x.size() << " " << comment << "\n"; + for(size_t i=0;i"); +} + +#endif // __FILE_H__ diff --git a/src/main/headers/funs.h b/src/main/headers/funs.h new file mode 100644 index 0000000..2d61630 --- /dev/null +++ b/src/main/headers/funs.h @@ -0,0 +1,413 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __FUNS_H__ +#define __FUNS_H__ + +#define Unimplemented throw_("Function unimplemented") +#define Dontgethere throw_("Dontgethere") + +#ifndef NDEBUG + #define ON_DEBUG(a) a +#else + #define ON_DEBUG(a) +#endif + +#ifdef USE_FFTW + extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size); +#endif + +// Small template funs +template bool isinmap (const map& m,const T& t) {return m.size()>=2 && m.begin()->first<=t && t<(--m.end())->first;} +template const size_t getsteps(const T& r0,const T& r1,const T& rstep,const bool logarithmic) {size_t N=0; for(T r=r0;r(&one))); + if (big) s+=" BIGENDIAN"; + else s+=" LITENDIAN"; + + return s; +} + +inline string FormatCompilerMsg(const string& file,const int line) +{ + #ifdef WIN32 + return file + ":" + line + ":"; + #else + return file + "(" + line + ")"; + #endif +} + +#ifdef WIN32 + extern "C"{ + #ifdef _UNICODE + #pragma message("ERROR: toolsfun cannot handle unicode...giving up compilation"); + ERROR_complier + #endif + + #ifdef _AFXDLL + __declspec(dllimport) void* __stdcall GetCurrentThread(); + __declspec(dllimport) void* __stdcall GetCurrentThreadId(); + __declspec(dllimport) int __stdcall SetThreadPriority(void* hThread,int nPriority); + #else + //void* __stdcall GetCurrentThread(); + //void* __stdcall GetCurrentThreadId(); + //int __stdcall SetThreadPriority(void* hThread,int nPriority); + __declspec(dllimport) void* __stdcall GetCurrentThread(); + __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); + __declspec(dllimport) int __stdcall SetThreadPriority(void* hThread,int nPriority); + __declspec(dllimport) int __stdcall GetThreadPriority(void* hThread); + __declspec(dllimport) unsigned int __stdcall WinExec(const char* lpCmdLine,unsigned int uCmdShow); + #ifndef _WINDOWS_ + __declspec(dllimport) unsigned int __stdcall MessageBox(void* hWnd,const char* lpText,const char* lpCaption,unsigned int Type); + __declspec(dllimport) unsigned long __stdcall GetCurrentDirectory(unsigned long nBufferLength,char* lpBuffer); + #endif + #endif + } +#else + int nice(int inc); +#endif + +inline int Message(const string& title,const string& msg,const int type) +{ +#ifdef WIN32 + // 0 = MB_OK + // 1 = MB_OKCANCEL + // 2 = MB_ABORTRETRYIGNORE + // 3 = MB_YESNOCANCEL + // 4 = MB_YESNO + // 5 = MB_RETRYCANCEL + // 6 = MB_CANCELTRYCONTINUE: if(WINVER >= 0x0500) + const long hr=MessageBox(NULL,msg.c_str(),title.c_str(),type); +#else + Unimplemented; +#endif + return 1; +} +/* +string GetCurrentDir() +{ +#ifdef WIN32 + char buff[16*1024]; + if(GetCurrentDirectory(16*1024,buff)==0) throw_("GetCurrentDirectory() failed"); + return tostring(buff); +#else + Unimplemented; + return ""; +#endif +} +*/ + +inline void SetNiceLevel(const int level) +{ + #ifdef WIN32 + // THREAD_PRIORITY_ABOVE_NORMAL 1 Priority 1 point above the priority class. + // THREAD_PRIORITY_BELOW_NORMAL -1 Priority 1 point below the priority class. + // THREAD_PRIORITY_HIGHEST 2 Priority 2 points above the priority class. + // THREAD_PRIORITY_IDLE -15 Base priority of 1 for IDLE_PRIORITY_CLASS,... + // THREAD_PRIORITY_LOWEST -2 Priority 2 points below the priority class. + // THREAD_PRIORITY_NORMAL 0 Normal priority for the priority class. + // THREAD_PRIORITY_TIME_CRITICAL 15 Base priority of 15 for IDLE_PRIORITY_CLASS,... + if (level!=0 && level!=1 && level!=-1 && level!=2 && level!=-2 && level!=15 && level!=-15) throw_("wrong Win32 nice level, must be oneof -15,-2,-1,0,1,2,15"); + SetThreadPriority(GetCurrentThread(),-level); + assert( GetThreadPriority(GetCurrentThread())==-level ); + #else + const int n=nice(level); + if (n<0) throw_("Could not set nice level"); + #endif +} + +inline size_t GetThreadId() +{ + #ifdef WIN32 + assert( sizeof(size_t)==sizeof(unsigned long) ); + return GetCurrentThreadId(); + #else + // may be replaced by return 0; if phtread not found! + assert( sizeof(size_t)==sizeof(pthread_t) ); + const pthread_t p=pthread_self(); + size_t q=0; + memcpy(&q,&p,sizeof(q)); + return q; + #endif +} + +#ifdef TOOLSFUN_QUIET_WIN32_SYSTEM +#ifdef WIN32 + // make a special non-console system call, instead of the standard system() + // XXX SystemWin, does not wait for process to finish, CreatProc still create window + + int SystemWin(const string& cmd) + { + //ShellExecute, CreateProcess, WinExec or system + // HINSTANCE hi=ShellExecute(NULL,NULL,cmdx,"","",SW_SHOSNOACTIVATE); + // if (reinterpret_cast(hi)<32) MessageBox(NULL,(string("ShellExecute <") + cmd + "> failed").c_str(),"Error",0); + + // const string cmd2="\\\"" + cmd + "\\\""; // fix problem with spaces in executable, not working yet + unsigned int r=WinExec(cmd.c_str(),4); + return r<32 ? -1 : 0; + } + + bool CreateProc(const string& cmd,const bool throwexception=true,const bool waitforprocesstofinish=true) + { + STARTUPINFO s; + PROCESS_INFORMATION p; + memset(&s,0,sizeof(s)); + memset(&p,0,sizeof(p)); + s.cb=sizeof(s); + + // to avoid const cast of char* in CreateProcess + char cmdx[16*1024]; + strcpy_s(cmdx,16*1024,cmd.c_str()); + + const int r=CreateProcess(0,cmdx,0,0,false,CREATE_DEFAULT_ERROR_MODE,0,0,&s,&p); + if (r!=0) {if(waitforprocesstofinish) WaitForSingleObject(p.hProcess,INFINITE);} + else { + if (throwexception) throw_(string("CreateProcess() failed with return code <") + GetLastError() + ">"); + else return false; + } + + // Release handles + assert(r!=0); + CloseHandle(p.hProcess); + CloseHandle(p.hThread); + return true; + } +#endif +#endif + +inline string System(const string& cmd,const bool throwexception=true,const bool captureoutput=false,int* pret=0) +{ + if (!captureoutput){ + #ifdef TOOLSFUN_QUIET_WIN32_SYSTEM + const int n=SystemWin(cmd); + #else + const int n=system(cmd.c_str()); + #endif + if (n!=0 && throwexception) throw_(string("system command failed with code=") + n + " cmd=<" + cmd + ">"); + if (pret!=0) *pret=n; + return ""; + } else { + static size_t n=0; + #ifdef WIN32 + const string rm="del "; + char tmp[1024]; + if (tmpnam_s(tmp,1024)) throw_("error in creating win32 temp name"); + const string file(tmp); + #else + const string rm="rm "; + const string file=tmpnam("tempfile"); + #endif + ifstream s1(file.c_str()); + if(s1) { + s1.close(); + System((rm + file).c_str(),true,false); + } + System(cmd + " > " + file,throwexception,false,pret); + + string t; + char buff[16*1024]; + ifstream s2(file.c_str()); + while(s2) { + s2.getline(buff,16*1024); + if (s2) t += buff; + } + s2.close(); + System((rm + file).c_str(),true,false); + return t; + } +} + +string Getlocaltime() +{ + FUNSTACK; + time_t rawtime; + time(&rawtime); + struct tm timeinfo; + localtime_s(&timeinfo,&rawtime); + char buff[1024]; + asctime_s(buff,1014,&timeinfo); + return string(buff); +} + +class timer +{ + private: + double m_t,m_cpu_t; + double* m_addt; + mutable double m_last_t,m_last_eta; + + static double gettime() + { + #ifdef WIN32 + return 1.0*clock()/CLOCKS_PER_SEC; // use low-res clock + // FILETIME ft; + // unsigned __int64 tmpres = 0; + // + // GetSystemTimeAsFileTime(&ft); + // + // tmpres |= ft.dwHighDateTime; + // tmpres <<= 32; + // tmpres |= ft.dwLowDateTime; + // + // converting file time to unix epoch + // tmpres -= DELTA_EPOCH_IN_MICROSECS; + // tmpres /= 10; // convert into microseconds + // tv->tv_sec = (long)(tmpres / 1000000UL); + // tv->tv_usec = (long)(tmpres % 1000000UL); + #else + struct timeval tv; + gettimeofday(&tv,NULL); + return tv.tv_sec + static_cast(tv.tv_usec)/1000000; + #endif + } + + static double getcputime() + { + static const double f=1.0/CLOCKS_PER_SEC; + return f*clock(); + } + + template + static double Remaining(const double t,const T& n,const T& N) + { + if (n>=N || N<=T(0)) throw_("value out of range in timer::Remaining, n>=N or N<=0, n=" + tostring(n) + " N=" + tostring(N)); + const double p=static_cast(n/T(1)+1)/(N/T(1)); + const double p2=p>0 ? t/p : 0; + return p2>t ? p2-t : 0; + } + + public: + timer() : m_t(gettime()), m_cpu_t(getcputime()), m_addt(0), m_last_t(-1), m_last_eta(-1) {} + timer(double& t) : m_t(gettime()), m_cpu_t(getcputime()), m_addt(&t), m_last_t(-1), m_last_eta(-1) {} + ~timer() {if (m_addt!=0) (*m_addt) += elapsed();} + + void reset () {m_t=gettime(); m_cpu_t=getcputime(); m_last_t=-1; m_last_eta=-1;} + double elapsed() const {return gettime()-m_t;} + double cputime() const {return getcputime()-m_cpu_t;} + + static string ToHMS(const double& t) + { + assert( t>=0 ); + const unsigned int it=static_cast(t+.5); + const unsigned int hours=it/(60*60); + const unsigned int mins=(it-hours*60*60)/(60); + const unsigned int secs=(it-hours*60*60-mins*60); + assert( secs<60 && mins<60); + return tostring(hours) + ":" + (mins<10 ? "0": "") + tostring(mins) + ":" + (secs<10 ? "0": "") + tostring(secs); + } + + template static inline int Topercent(const T x,const T N,const int decimals=-1) + { + assert(x(x/T(1))/(N/T(1)); + if (decimals>0) pf=static_cast(pf*decimals)/(1.0*decimals); + return static_cast(pf*100+.5); + } + + template void ToEta(const T& n,const T& N,ostream& s,const double timeprintsteps=30,const bool verboseprint=false) const + { + if (n>=N) return; + assert( ntimeprintsteps) { + const double f=timeprintsteps*60; + const double r=Remaining(t,n,N); + if (m_last_eta<0 || rf && e>f) /*|| (m_last_eta>0 && r>1.2*m_last_eta) */ ){ + time_t tm; + time(&tm); + const string systime=ctime(&tm); + if (m_last_eta<0) s << "Current system time: " << systime; + tm += static_cast(r); + const string eta=ctime(&tm); + const bool extraday=(eta.substr(0,3)!=systime.substr(0,3)); + const string eday=extraday ? " "+eta.substr(0,3)+" " : ""; + s << "Time [h:m:s]=" << ToHMS(t) << ", R=" << ToHMS(r) << ", ETA=" << eday << eta.substr(11,8); + if(verboseprint) { + const string t=", n/N=" + tostring(n) + "/" + tostring(N) + "=" + tostring(Topercent(n,N,10)) + " percent,"; + s << t; + for(size_t i=t.size();i<42;++i) s << " "; + s << " CPU=" << ToHMS(cputime()); + } + s << endl; + + m_last_t=t; + m_last_eta=r; + } + } + } + friend ostream& operator<<(ostream& s,const timer x) + { + return s << "Time [h:m:s]= " << x.ToHMS(x.elapsed()) << " CPU=" << x.ToHMS(x.cputime()); + } +}; + +/* +int SwapEndian(void *data,const size_t size) { + + short xs; + long xl; + + switch (size){ + case 2: + xs = *(short *)data; + *(short *)data = ( ((xs & 0x0000ff00) >> 8) | ((xs & 0x000000ff) << 8) ); + break; + case 4: + xl = *(long *)data; + *(long *)data = ( ((xl & 0xff000000) >> 24) | ((xl & 0x00ff0000) >> 8) | + ((xl & 0x0000ff00) << 8) | ((xl & 0x000000ff) << 24) ); + break; + default: break; + } + + return 0; +} +*/ + +#endif // __FUNS_H__ diff --git a/src/main/headers/process.h b/src/main/headers/process.h new file mode 100644 index 0000000..77ffc52 --- /dev/null +++ b/src/main/headers/process.h @@ -0,0 +1,282 @@ +#ifndef __PROCESS_H__ +#define __PROCESS_H__ + +#include + +pair ProcessWalkInit() +{ + // Take a snapshot of all processes in the system. + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); + if( hProcessSnap == INVALID_HANDLE_VALUE ) throw_("CreateToolhelp32Snapshot() returned invalid handle"); + + // Set the size of the structure before using it. + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + // Retrieve information about the first process, + // and exit if unsuccessful + if(!Process32First(hProcessSnap,&pe32)) { + CloseHandle(hProcessSnap); // clean the snapshot object + throw_("Process32First"); // show cause of failure + } + + return make_pair(hProcessSnap,pe32); +} + +DWORD GetProcessID(const string& processname) +{ + pair h=ProcessWalkInit(); + HANDLE hProcessSnap=h.first; + PROCESSENTRY32 pe32=h.second; + + do { + if (pe32.szExeFile==processname) { + CloseHandle(hProcessSnap); + return pe32.th32ProcessID; + } + } while( Process32Next(hProcessSnap,&pe32) ); + + CloseHandle(hProcessSnap); + return 0; +} + +PROCESSENTRY32 GetProcessInfo(const DWORD id) +{ + pair h=ProcessWalkInit(); + HANDLE hProcessSnap=h.first; + PROCESSENTRY32 pe32=h.second; + + int n=0; + do { + if (pe32.th32ProcessID==id) { + CloseHandle(hProcessSnap); + return pe32; + } + } while( Process32Next(hProcessSnap,&pe32) ); + + CloseHandle(hProcessSnap); + ZeroMemory( &pe32, sizeof(pe32) ); + pe32.dwSize = sizeof(PROCESSENTRY32); + + return pe32; +} + +DWORD GetProcessCount(const string& processname) +{ + pair h=ProcessWalkInit(); + HANDLE hProcessSnap=h.first; + PROCESSENTRY32 pe32=h.second; + int n=0; + do { + if (pe32.szExeFile==processname) ++n; + } while( Process32Next(hProcessSnap,&pe32) ); + + CloseHandle(hProcessSnap); + return n; +} + +bool KillProcessID(const DWORD id) +{ + HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, id); + if(hProcess==NULL) return false; // might have gone in the meantime, so no throw_("OpenProcess() got null handle"); + + const BOOL t=TerminateProcess(hProcess,-1); + CloseHandle(hProcess); + return t!=0; +} + +void KillAllProcesses(const string& exe) +{ + // kill existing polls + DWORD id=GetProcessID(exe); + while(id!=0){ + KillProcessID(id); + id=GetProcessID(exe); + } +} + +/* +#include +#include +#include + +BOOL GetProcessList( ); +BOOL ListProcessModules( DWORD dwPID ); +BOOL ListProcessThreads( DWORD dwOwnerPID ); +void printError( TCHAR* msg ); + +FILE* log=fopen("d:\\plog.txt","w"); + +BOOL GetProcessList( ) +{ + HANDLE hProcessSnap; + HANDLE hProcess; + PROCESSENTRY32 pe32; + DWORD dwPriorityClass; + + // Take a snapshot of all processes in the system. + hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + if( hProcessSnap == INVALID_HANDLE_VALUE ) + { + printError( TEXT("CreateToolhelp32Snapshot (of processes)") ); + return( FALSE ); + } + + // Set the size of the structure before using it. + pe32.dwSize = sizeof( PROCESSENTRY32 ); + + // Retrieve information about the first process, + // and exit if unsuccessful + if( !Process32First( hProcessSnap, &pe32 ) ) + { + printError( TEXT("Process32First") ); // show cause of failure + CloseHandle( hProcessSnap ); // clean the snapshot object + return( FALSE ); + } + + // Now walk the snapshot of processes, and + // display information about each process in turn + do + { + fprintf(log, "\n\n=====================================================" ); + fprintf(log, TEXT("\nPROCESS NAME: %s"), pe32.szExeFile ); + fprintf(log, "\n-----------------------------------------------------" ); + + // Retrieve the priority class. + dwPriorityClass = 0; + hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); + if( hProcess == NULL ) + printError( TEXT("OpenProcess") ); + else + { + dwPriorityClass = GetPriorityClass( hProcess ); + if( !dwPriorityClass ) + printError( TEXT("GetPriorityClass") ); + CloseHandle( hProcess ); + } + + fprintf(log, "\n Process ID = 0x%08X", pe32.th32ProcessID ); + fprintf(log, "\n Thread count = %d", pe32.cntThreads ); + fprintf(log, "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID ); + fprintf(log, "\n Priority base = %d", pe32.pcPriClassBase ); + if( dwPriorityClass ) + fprintf(log, "\n Priority class = %d", dwPriorityClass ); + + // List the modules and threads associated with this process + ListProcessModules( pe32.th32ProcessID ); + ListProcessThreads( pe32.th32ProcessID ); + + } while( Process32Next( hProcessSnap, &pe32 ) ); + + CloseHandle( hProcessSnap ); + return( TRUE ); +} + + +BOOL ListProcessModules( DWORD dwPID ) +{ + HANDLE hModuleSnap = INVALID_HANDLE_VALUE; + MODULEENTRY32 me32; + + // Take a snapshot of all modules in the specified process. + hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); + if( hModuleSnap == INVALID_HANDLE_VALUE ) + { + printError( TEXT("CreateToolhelp32Snapshot (of modules)") ); + return( FALSE ); + } + + // Set the size of the structure before using it. + me32.dwSize = sizeof( MODULEENTRY32 ); + + // Retrieve information about the first module, + // and exit if unsuccessful + if( !Module32First( hModuleSnap, &me32 ) ) + { + printError( TEXT("Module32First") ); // show cause of failure + CloseHandle( hModuleSnap ); // clean the snapshot object + return( FALSE ); + } + + // Now walk the module list of the process, + // and display information about each module + do + { + fprintf(log, TEXT("\n\n MODULE NAME: %s"), me32.szModule ); + fprintf(log, TEXT("\n Executable = %s"), me32.szExePath ); + fprintf(log, "\n Process ID = 0x%08X", me32.th32ProcessID ); + fprintf(log, "\n Ref count (g) = 0x%04X", me32.GlblcntUsage ); + fprintf(log, "\n Ref count (p) = 0x%04X", me32.ProccntUsage ); + fprintf(log, "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr ); + fprintf(log, "\n Base size = %d", me32.modBaseSize ); + + } while( Module32Next( hModuleSnap, &me32 ) ); + + CloseHandle( hModuleSnap ); + return( TRUE ); +} + +BOOL ListProcessThreads( DWORD dwOwnerPID ) +{ + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + // Take a snapshot of all running threads + hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); + if( hThreadSnap == INVALID_HANDLE_VALUE ) + return( FALSE ); + + // Fill in the size of the structure before using it. + te32.dwSize = sizeof(THREADENTRY32); + + // Retrieve information about the first thread, + // and exit if unsuccessful + if( !Thread32First( hThreadSnap, &te32 ) ) + { + printError( TEXT("Thread32First") ); // show cause of failure + CloseHandle( hThreadSnap ); // clean the snapshot object + return( FALSE ); + } + + // Now walk the thread list of the system, + // and display information about each thread + // associated with the specified process + do + { + if( te32.th32OwnerProcessID == dwOwnerPID ) + { + fprintf(log, "\n\n THREAD ID = 0x%08X", te32.th32ThreadID ); + fprintf(log, "\n Base priority = %d", te32.tpBasePri ); + fprintf(log, "\n Delta priority = %d", te32.tpDeltaPri ); + } + } while( Thread32Next(hThreadSnap, &te32 ) ); + + CloseHandle( hThreadSnap ); + return( TRUE ); +} + +void printError( TCHAR* msg ) +{ + DWORD eNum; + TCHAR sysMsg[256]; + TCHAR* p; + + eNum = GetLastError( ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, eNum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + sysMsg, 256, NULL ); + + // Trim the end of the line and terminate it with a null + p = sysMsg; + while( ( *p > 31 ) || ( *p == 9 ) ) + ++p; + do { *p-- = 0; } while( ( p >= sysMsg ) && + ( ( *p == '.' ) || ( *p < 33 ) ) ); + + // Display the message + fprintf(log, TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg ); +} +*/ + +#endif // __PROCESS_H__ \ No newline at end of file diff --git a/src/main/headers/reg.h b/src/main/headers/reg.h new file mode 100644 index 0000000..5d3d565 --- /dev/null +++ b/src/main/headers/reg.h @@ -0,0 +1,95 @@ +#ifndef __REGISTRY_H__ +#define __REGISTRY_H__ + +#ifdef WIN32 +#ifdef _WINDOWS + +namespace Registry{ + void* StringtoRoot(const string& t) + { + if (t=="HKEY_CLASSES_ROOT") return HKEY_CLASSES_ROOT; + else if (t=="HKEY_CURRENT_USER") return HKEY_CURRENT_USER; + else if (t=="HKEY_LOCAL_MACHINE") return HKEY_LOCAL_MACHINE; + else if (t=="HKEY_USERS") return HKEY_USERS; + else {throw_("bad root path in registry"); return 0;} + } + + pair > GetPath(const string& fullpath) + { + const int n=fullpath.find_first_of('\\'); + if (n==string::npos) throw_("mallformated registry entry"); + const string t=fullpath.substr(0,n); + void* root=StringtoRoot(t); + + const string r=fullpath.substr(n+1,-1); + const int m=r.find_last_of('\\'); + if (m==string::npos) throw_("mallformated registry entry"); + + const string path=r.substr(0,m); + const string key =r.substr(m+1,-1); + + return make_pair(root,make_pair(path,key)); + } + + bool hasKey(void* root,const string& path,const string& key,string* val=0) + { + assert( sizeof(void*)==sizeof(HKEY) && root!=0 ); + if (root!=HKEY_CLASSES_ROOT && root!=HKEY_CURRENT_USER && root!=HKEY_LOCAL_MACHINE && root!=HKEY_USERS) throw_("unknown root path in registry"); + + DWORD buffersize=1024*16; + char buff[1024*16]; + buff[0]=0; + + HKEY hKey; + if (ERROR_SUCCESS!=RegOpenKeyEx(static_cast(root),path.c_str(),NULL,KEY_READ,&hKey)) return false; + if (ERROR_SUCCESS!=RegQueryValueEx(hKey,key.c_str(),NULL,NULL,(LPBYTE)buff,&buffersize)) return false; + if (ERROR_SUCCESS!=RegCloseKey(hKey)) return false; + + if (val!=0) *val=buff; + return true; + } + + string GetKey(void* root,const string& path,const string& key) + { + string val; + if (!hasKey(root,path,key,&val)) throw_("could not read registry entry"); + return val; + } + + string GetKey(const string& fullpath) + { + const pair > p=GetPath(fullpath); + return GetKey(p.first,p.second.first,p.second.second); + } + + bool SetKey(void* root,const string& path,const string& key,const string& val) + { + assert( sizeof(void*)==sizeof(HKEY) && root!=0 ); + if (root!=HKEY_CLASSES_ROOT && root!=HKEY_CURRENT_USER && root!=HKEY_LOCAL_MACHINE && root!=HKEY_USERS) throw_("unknown root path in registry"); + if (val.size()+1>1024*16) throw_("lenght of value to long"); + + char buff[1024*16]; + size_t i; + for(i=0;i(root),path.c_str(),0,NULL,REG_OPTION_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL)) return false; + if (ERROR_SUCCESS!=RegSetValueEx(hKey,key.c_str(),NULL,REG_SZ,(LPBYTE)buff,buffersize)) return false; + if (ERROR_SUCCESS!=RegCloseKey(hKey)) return false; + + return true; + } + + bool SetKey(const string& fullpath,const string& val) + { + const pair > p=GetPath(fullpath); + return SetKey(p.first,p.second.first,p.second.second,val); + } + +}; // namespace Registry + +#endif // _WINDOWS +#endif // WIN32 +#endif // __REGISTRY_H__ \ No newline at end of file diff --git a/src/main/headers/stringfun.h b/src/main/headers/stringfun.h new file mode 100644 index 0000000..9624292 --- /dev/null +++ b/src/main/headers/stringfun.h @@ -0,0 +1,284 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __STRINGFUN_H__ +#define __STRINGFUN_H__ + +struct outputoperator_tags +{ + string preline,endline; + int prewidth,postwidth,precision; + bool maptags,printnumbers,serialize; + + outputoperator_tags() + : endline("\n"), prewidth(-1), postwidth(-1), precision(-1), maptags(false), printnumbers(false), serialize(false) {} +}; + +static outputoperator_tags g_tags; + +inline ostream& operator<<(ostream& os,const outputoperator_tags& x){ + g_tags=x; + if (g_tags.precision>0) os.precision(g_tags.precision); + return os; +} + +template +inline string tostring(const T& x) +{ + ostringstream os; + outputoperator_tags t1=g_tags; + g_tags=outputoperator_tags(); + g_tags.serialize=true; + g_tags.endline=""; + os << x; + g_tags=t1; + return os.str(); +} + +template +inline T totype(const string& s) +{ + istringstream is(s); + T x; + is >> x; + return x; +} + +inline string operator+ (const string& s,const char* c) {return s+string(c);} +inline string operator+ (const string& s,const short& c) {return s+tostring(c);} +inline string operator+ (const string& s,const unsigned short& c) {return s+tostring(c);} +inline string operator+ (const string& s,const int& c) {return s+tostring(c);} +inline string operator+ (const string& s,const long& c) {return s+tostring(c);} +inline string operator+ (const string& s,const unsigned long& c) {return s+tostring(c);} +inline string operator+ (const string& s,const float& c) {return s+tostring(c);} +inline string operator+ (const string& s,const double& c) {return s+tostring(c);} +inline string operator+ (const string& s,const long double& c) {return s+tostring(c);} +inline string operator+ (const char* a ,const string& b) {return string(a)+b;} + +#ifdef OS_Linux +#ifdef __GCC_V4__ + // does not work under some compilers where size_t==unsigned int + inline string operator+ (const string& s,const size_t& c) {return s+tostring(c);} +#endif +#endif + +inline string tostring(const int argc,char** argv) +{ + string s; + for(int i=0;i +inline string fwidth2(const T& x,const size_t wdt,const bool prefix) +{ + string s=tostring(x); + if(wdt>1024 || s.size()>=wdt) return s; + size_t n=wdt-s.size(); + while(n>0) { + if (prefix) s=' '+ s; + else s+=' '; + --n; + } + return s; +} + +template +inline string fwidth(const T& x,const size_t wdt=8,const size_t tailwdt=4) +{ + string s=tostring(x); + if(wdt>1024 || tailwdt>1024 || s.size()>wdt+tailwdt) return s; + + const size_t m=min(s.find('.'),s.find(' ')); + if (m==string::npos) { + s=fwidth2(s,wdt,true); + return fwidth2(s,wdt+tailwdt,false); + } + else{ + if(wdt=m ); + size_t n1=wdt-m; + while(n1>0) {s= ' ' + s; --n1;} + return fwidth2(s,wdt+tailwdt,false); + } +} + +inline string strip(const string& s,const char ch=' ') +{ + const size_t n=s.find_first_not_of(ch); + const size_t m=s.find_last_not_of (ch); + + if (n==string::npos || m==string::npos) return ""; + return s.substr(n,m-n+1); +} + +inline string replace(const string& s,const string& f,const string& r) +{ + if (f.size()==0) return s; + const size_t n=s.find(f); + if (n==string::npos) return s; + else return replace(s.substr(0,n) + r + s.substr(n+f.size()),f,r); +} + +inline string indent(const string& s,const string& indent) +{ + string t,q=s; + while(q.size()){ + const string::size_type n=q.find_first_of("\n"); + t += indent + q.substr(0,n) + "\n"; + if (n==string::npos) break; + assert(n+1<=q.size()); + q = q.substr(n+1,q.size()); + } + return t; +} + +inline string removerems(const string& s,const string rem) +{ + const size_t n=s.find_first_of(rem); + return s.substr(0,n); +} + +inline string suffix(const int n) +{ + assert(n>=0 && n<999); + if (n<=9) return "00" + tostring(n); + else if (n<=99) return "0" + tostring(n); + else return tostring(n); +} + +string tail(const string& s,const string& delimiter) +{ + const size_t n=s.find_last_of(delimiter); + if (n==string::npos) return s; + else return s.substr(n+delimiter.size(),-1); +} + +string tail(const string& s,const char c) { + string t; + t.resize(1); + t[0]=c; + return tail(s,t); +} + +template +inline ostream& operator<<(ostream& os,const pair x) +{ + for(int i=0;i +inline istream& operator>>(istream& is,pair x) +{ + for(int i=0;i> x.first[i]; + return is; +} + +template +inline ostream& operator<<(ostream& s,const vector& x) +{ + int i=0; + if (g_tags.serialize) s << "vector: " << x.size() << " { "; + for(typename vector::const_iterator itt=x.begin();itt!=x.end();++itt) { + s << g_tags.preline; + if(g_tags.printnumbers) s << "[" << fwidth(++i,3,0) << "] "; + s << *itt << " " << g_tags.endline; + } + if (g_tags.serialize) s << "} "; + return s; +} + +template +inline istream& operator>>(istream& s,vector& x) +{ + size_t n=0; + string t; + s >> t; + if (t!="vector:") throw_("bad format in vector serialization stream, tag missing"); + s >> n >> t; + if (t!="{") throw_("bad format in vector serialization stream, missing begin brace"); + x.resize(n); + for(size_t i=0;i> x[i]; + s >> t; + if (t!="}") throw_("bad format in vector serialization stream, missing end brace"); + return s; +} + +template +inline ostream& operator<<(ostream& s,const list& x) +{ + if (g_tags.serialize) s << "list: " << x.size() << " { "; + int i=0; + for(typename list::const_iterator itt=x.begin();itt!=x.end();++itt){ + s << g_tags.preline; + if(g_tags.printnumbers) s << "[" << fwidth(++i,3,0) << "] "; + s << *itt << " " << g_tags.endline; + } + if (g_tags.serialize) s << "} "; + return s; +} + +template +inline istream& operator>>(istream& s,list& x) +{ + size_t n=0; + string t; + s >> t; + if (t!="list:") throw_("bad format in list serialization stream, tag missing"); + s >> n >> t; + if (t!="{") throw_("bad format in list serialization stream, missing begin brace"); + for(size_t i=0;i> y; + x.push_back(y); + } + s >> t; + if (t!="}") throw_("bad format in list serialization stream, missing end brace"); + return s; +} + +template +inline ostream& operator<<(ostream& s,const map& x) +{ + if (g_tags.serialize) s << "map: " << x.size() << " { "; + int i=0; + for(typename map::const_iterator itt=x.begin();itt!=x.end();++itt) { + s << g_tags.preline; + if(g_tags.printnumbers) s << "[" << fwidth(++i,3,0) << "] "; + s << fwidth(itt->first,g_tags.prewidth,g_tags.postwidth) << (g_tags.maptags ? " |-> " : " "); + s << fwidth(itt->second,g_tags.prewidth,g_tags.postwidth) << " " << g_tags.endline; + } + if (g_tags.serialize) s << "} "; + return s; +} + +template +inline istream& operator>>(istream& s,map& x) +{ + size_t n=0; + string t; + s >> t; + if (t!="map:") throw_("bad format in map serialization stream, tag missing"); + s >> n >> t; + if (t!="{") throw_("bad format in map serialization stream, missing begin brace"); + for(size_t i=0;i> y >> z; + if (x.find(y)!=x.end()) throw_("bad stream, key value no unique"); + x[y]=z; + } + s >> t; + if (t!="}") throw_("bad format in map serialization stream, missing end brace"); + return s; +} + +#endif // __STRINGFUNS_H__ diff --git a/src/main/headers/templatefun.h b/src/main/headers/templatefun.h new file mode 100644 index 0000000..0cb60e9 --- /dev/null +++ b/src/main/headers/templatefun.h @@ -0,0 +1,52 @@ +#ifndef __TEMPLATE_FUN__ +#define __TEMPLATE_FUN__ + +template +class Autobool +{ +private: + volatile T* m_b; + Autobool(const Autobool&); + void operator=(const Autobool&); +public: + Autobool(volatile T* b) : m_b(b) {assert(m_b && *m_b==false); *m_b=true;} + ~Autobool() {assert(m_b && *m_b==true); *m_b=false; m_b=0;} +}; + +template +class DeviceAutoClose +{ +private: + T m_dev; + R (__stdcall *m_fun)(void *); + bool m_init; + + // private Copy CTOR and assignment operator + DeviceAutoClose(const DeviceAutoClose&); + void operator=(const DeviceAutoClose&); + +public: + DeviceAutoClose(T dev,R(__stdcall *fun)(void*)) : m_dev(dev), m_fun(fun), m_init(true) + { + FUNSTACK; + assert(m_fun!=NULL); + } + ~DeviceAutoClose() + { + FUNSTACK; + assert(m_init); + assert(m_fun!=NULL); + if (m_dev!=NULL){ + R r=m_fun(m_dev); + if (!r) throw_("DeviceClose() failed"); // throw in DTOR -> bad, bad! + } + m_dev=NULL; + m_fun=NULL; + m_init=false; + } + const T& operator()() const {FUNSTACK; assert(m_init); return m_dev;} + T& operator()() {FUNSTACK; assert(m_init); return m_dev;} +}; + + +#endif // __TEMPLATE_FUN__ \ No newline at end of file diff --git a/src/main/headers/toolsfun.h b/src/main/headers/toolsfun.h new file mode 100644 index 0000000..88a7e76 --- /dev/null +++ b/src/main/headers/toolsfun.h @@ -0,0 +1,34 @@ +// The code is copyrighted 2008 by Carsten Frigaard. +// All rights placed in public domain under GNU licence V2, 2008 +// +// © 2008 Carsten Frigaard. Permission to use, copy, modify, and distribute this software +// and its documentation for any purpose and without fee is hereby granted, provided that +// the above copyright notice appear in all copies and that both that copyright notice +// and this permission notice appear in supporting documentation. + +#ifndef __TOOLSFUN_H__ +#define __TOOLSFUN__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#include "exception.h" +#include "stringfun.h" +#include "args.h" +#include "funs.h" +#include "file.h" +#include "configfile.h" +#include "templatefun.h" +#include "reg.h" + +#endif // __TOOLSFUN_H__ diff --git a/src/main/headers/usbm.h b/src/main/headers/usbm.h new file mode 100644 index 0000000..802c942 --- /dev/null +++ b/src/main/headers/usbm.h @@ -0,0 +1,204 @@ +#ifndef __USBM_H__ +#define __USBM_H__ + +class USBio +{ +private: + HINSTANCE m_hDll; + + // Discovery routine + typedef int (__stdcall *USBm_FindDevices_type) (); + + // Info about devices + typedef int (__stdcall *USBm_NumberOfDevices_type) (void); + typedef int (__stdcall *USBm_DeviceValid_type) (unsigned char); + typedef int (__stdcall *USBm_DeviceVID_type) (unsigned char device); + typedef int (__stdcall *USBm_DevicePID_type) (unsigned char device); + typedef int (__stdcall *USBm_DeviceDID_type) (unsigned char device); + typedef int (__stdcall *USBm_DeviceMfr_type) (unsigned char, char *); + typedef int (__stdcall *USBm_DeviceProd_type) (unsigned char, char *); + typedef int (__stdcall *USBm_DeviceSer_type) (unsigned char, char *); + + // General U4xx functions + typedef int (__stdcall *USBm_InitPorts_type) (unsigned char); + typedef int (__stdcall *USBm_WriteA_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_WriteB_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_WriteABit_type) (unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_WriteBBit_type) (unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_ReadA_type) (unsigned char, unsigned char *); + typedef int (__stdcall *USBm_ReadB_type) (unsigned char, unsigned char *); + typedef int (__stdcall *USBm_SetBit_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_ResetBit_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_DirectionA_type) (unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_DirectionB_type) (unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_StrobeWrite_type) (unsigned char, unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_StrobeRead_type) (unsigned char, unsigned char *, unsigned char, unsigned char); + typedef int (__stdcall *USBm_StrobeWrite2_type) (unsigned char, unsigned char, unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_StrobeRead2_type) (unsigned char, unsigned char *, unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_StrobeWrites_type) (unsigned char, unsigned char *, unsigned char *); + typedef int (__stdcall *USBm_StrobeReads_type) (unsigned char, unsigned char *, unsigned char *); + typedef int (__stdcall *USBm_InitLCD_type) (unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_LCDCmd_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_LCDData_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_InitSPI_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_SPIMaster_type) (unsigned char, unsigned char *, unsigned char *); + typedef int (__stdcall *USBm_SPISlaveWrite_type) (unsigned char, unsigned char, unsigned char *); + typedef int (__stdcall *USBm_SPISlaveRead_type) (unsigned char, unsigned char *, unsigned char *); + typedef int (__stdcall *USBm_Stepper_type) (unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char); + typedef int (__stdcall *USBm_Reset1Wire_type) (unsigned char, unsigned char *); + typedef int (__stdcall *USBm_Write1Wire_type) (unsigned char, unsigned char); + typedef int (__stdcall *USBm_Read1Wire_type) (unsigned char, unsigned char *); + + // DLL string info access + typedef int (__stdcall *USBm_RecentError_type) (char *); + typedef int (__stdcall *USBm_ClearRecentError_type) (void); + typedef int (__stdcall *USBm_DebugString_type) (char *); + typedef int (__stdcall *USBm_Copyright_type) (char *); + typedef int (__stdcall *USBm_About_type) (char *); + typedef int (__stdcall *USBm_Version_type) (char *); + +public: + USBio() : m_hDll(0) + { + m_hDll = LoadLibrary("USBm.dll"); + if (m_hDll==0) throw_("could not locate USBm.dll"); + + USBm_FindDevices = (USBm_FindDevices_type)GetProcAddress(m_hDll, "USBm_FindDevices"); + USBm_NumberOfDevices = (USBm_NumberOfDevices_type)GetProcAddress(m_hDll, "USBm_NumberOfDevices"); + USBm_DeviceValid = (USBm_DeviceValid_type)GetProcAddress(m_hDll, "USBm_DeviceValid"); + USBm_DeviceVID = (USBm_DeviceVID_type)GetProcAddress(m_hDll, "USBm_DeviceVID"); + USBm_DevicePID = (USBm_DevicePID_type)GetProcAddress(m_hDll, "USBm_DevicePID"); + USBm_DeviceDID = (USBm_DeviceDID_type)GetProcAddress(m_hDll, "USBm_DeviceDID"); + USBm_DeviceMfr = (USBm_DeviceMfr_type)GetProcAddress(m_hDll, "USBm_DeviceMfr"); + USBm_DeviceProd = (USBm_DeviceProd_type)GetProcAddress(m_hDll, "USBm_DeviceProd"); + USBm_DeviceSer = (USBm_DeviceSer_type)GetProcAddress(m_hDll, "USBm_DeviceSer"); + USBm_InitPorts = (USBm_InitPorts_type)GetProcAddress(m_hDll, "USBm_InitPorts"); + USBm_WriteA = (USBm_WriteA_type)GetProcAddress(m_hDll, "USBm_WriteA"); + USBm_WriteB = (USBm_WriteB_type)GetProcAddress(m_hDll, "USBm_WriteB"); + USBm_WriteABit = (USBm_WriteABit_type)GetProcAddress(m_hDll, "USBm_WriteABit"); + USBm_WriteBBit = (USBm_WriteBBit_type)GetProcAddress(m_hDll, "USBm_WriteBBit"); + USBm_ReadA = (USBm_ReadA_type)GetProcAddress(m_hDll, "USBm_ReadA"); + USBm_ReadB = (USBm_ReadB_type)GetProcAddress(m_hDll, "USBm_ReadB"); + USBm_SetBit = (USBm_SetBit_type)GetProcAddress(m_hDll, "USBm_SetBit"); + USBm_ResetBit = (USBm_ResetBit_type)GetProcAddress(m_hDll, "USBm_ResetBit"); + USBm_DirectionA = (USBm_DirectionA_type)GetProcAddress(m_hDll, "USBm_DirectionA"); + USBm_DirectionB = (USBm_DirectionB_type)GetProcAddress(m_hDll, "USBm_DirectionB"); + USBm_StrobeWrite = (USBm_StrobeWrite_type)GetProcAddress(m_hDll, "USBm_StrobeWrite"); + USBm_StrobeRead = (USBm_StrobeRead_type)GetProcAddress(m_hDll, "USBm_StrobeRead"); + USBm_StrobeWrite2 = (USBm_StrobeWrite2_type)GetProcAddress(m_hDll, "USBm_StrobeWrite2"); + USBm_StrobeRead2 = (USBm_StrobeRead2_type)GetProcAddress(m_hDll, "USBm_StrobeRead2"); + USBm_StrobeWrites = (USBm_StrobeWrites_type)GetProcAddress(m_hDll, "USBm_StrobeWrites"); + USBm_StrobeReads = (USBm_StrobeReads_type)GetProcAddress(m_hDll, "USBm_StrobeReads"); + USBm_InitLCD = (USBm_InitLCD_type)GetProcAddress(m_hDll, "USBm_InitLCD"); + USBm_LCDCmd = (USBm_LCDCmd_type)GetProcAddress(m_hDll, "USBm_LCDCmd"); + USBm_LCDData = (USBm_LCDData_type)GetProcAddress(m_hDll, "USBm_LCDData"); + USBm_InitSPI = (USBm_InitSPI_type)GetProcAddress(m_hDll, "USBm_InitSPI"); + USBm_SPIMaster = (USBm_SPIMaster_type)GetProcAddress(m_hDll, "USBm_SPIMaster"); + USBm_SPISlaveWrite = (USBm_SPISlaveWrite_type)GetProcAddress(m_hDll, "USBm_SPISlaveWrite"); + USBm_SPISlaveRead = (USBm_SPISlaveRead_type)GetProcAddress(m_hDll, "USBm_SPISlaveRead"); + USBm_Stepper = (USBm_Stepper_type)GetProcAddress(m_hDll, "USBm_Stepper"); + USBm_Reset1Wire = (USBm_Reset1Wire_type)GetProcAddress(m_hDll, "USBm_Reset1Wire"); + USBm_Write1Wire = (USBm_Write1Wire_type)GetProcAddress(m_hDll, "USBm_Write1Wire"); + USBm_Read1Wire = (USBm_Read1Wire_type)GetProcAddress(m_hDll, "USBm_Read1Wire"); + USBm_RecentError = (USBm_RecentError_type)GetProcAddress(m_hDll, "USBm_RecentError"); + USBm_ClearRecentError = (USBm_ClearRecentError_type)GetProcAddress(m_hDll, "USBm_ClearRecentError"); + USBm_DebugString = (USBm_DebugString_type)GetProcAddress(m_hDll, "USBm_DebugString"); + USBm_Copyright = (USBm_Copyright_type)GetProcAddress(m_hDll, "USBm_Copyright"); + USBm_About = (USBm_About_type)GetProcAddress(m_hDll, "USBm_About"); + USBm_Version = (USBm_Version_type)GetProcAddress(m_hDll, "USBm_Version"); + } + + ~USBio() + { + assert( m_hDll ); +// XXX FreeLibrary(m_hDll); + m_hDll=0; + } + + int Devices() const + { + assert( m_hDll ); + unsigned char numdev=USBm_NumberOfDevices(); + return numdev; + } + + string version() const + { + assert( m_hDll ); + + string s; + char textstr[300]; + const int d=Devices(); + + s = string(" USBm.dll version = ") + USBm_Version(textstr) + "\n"; + s += string(" USBm.dll version = ") + textstr + "\n"; + + USBm_Copyright(textstr); + s += string(" Copyright = ") + textstr + "\n"; + + USBm_About(textstr); + s += string(" About =") + textstr + "\n"; + s += string(" Number of devices = ") + d + "\n"; + + // Gather info from each discovered device + for(int i=0;i. +// This is free software: you are free to change and redistribute it. +// There is NO WARRANTY, to the extent permitted by law. +// +// This file is part of wiiscan. +// +// wiiscan is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// wiiscan is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with wiiscan. If not, see . + +#define VERSION 0 +#define VERSION_REV 9 + +#define VC_EXTRALEAN + +#include "toolsfun.h" +#include "wiiuse.h" +#include "usbm.h" +#include "delcomdll.h" +#include +#include + +#pragma comment ( lib, "Lib/wiiuse.lib") +#pragma comment ( lib, "Lib/delcomdll.lib") +#pragma comment ( lib, "Irprops.lib") +#pragma comment ( lib, "Ws2_32.lib") + +namespace Wiiscan { + +// default values +const int MAX_DEVICE_COUNT =256; +const int DEFAULT_timeout =2000; +const int DEFAULT_wiitimeout=2000; +const int DEFAULT_usbsleep =500; +const int DEFAULT_usbmsleep =3000; +const int DEFAULT_btsleep =2000; +const int DEFAULT_usbmode =0; +const int DEFAULT_removemode=0; +const int DEFAULT_scanretries=1; +const string NINTENDO_DEV="Nintendo RVL-CNT-01"; +const string DEFAULT_configfile="wiiscan.ini"; +const string DEFAULT_logfile="cout"; +const string DEFAULT_wiilib="wiimotelib"; + +Logger& log=g_log; +void (*g_automode_callback)(const int)=0; +void DummyCallback(const int){FUNSTACK;} + +string ConvertName(const WCHAR* szName) +{ + FUNSTACK; + assert( MAX_PATH >= BLUETOOTH_MAX_NAME_SIZE ); + CHAR szDevName[MAX_PATH]; + memset(szDevName, 0x00, sizeof(szDevName)); + sprintf_s(szDevName,MAX_PATH,"%S", szName); + return string(szDevName); +} + +string ConvertAddress(const BLUETOOTH_ADDRESS& address) +{ + FUNSTACK; + string s; + char t[256]; + for(int i=5;i>=0;i--) { + sprintf_s(t,256,"%X",address.rgBytes[i]); + string x=t; + if (x.size()==1) x="0"+x; + s+=x+(i==0 ? "" : ":"); + } + return s; +} + +string tostring(const SYSTEMTIME& x) +{ + FUNSTACK; + // XXX warning: no converstion of GMT to local time + ostringstream s; + if (x.wHour==0 && x.wMinute==0 && x.wDay==0 && x.wYear==0 && x.wYear==0) s << ""; + else s << x.wHour << ":" << (x.wMinute<10 ? "0" : "") << x.wMinute << " d. " << x.wDay << "/" << x.wMonth << ", " << x.wYear; + return s.str(); +} + +string tostring(const BLUETOOTH_DEVICE_INFO& x) +{ + FUNSTACK; + ostringstream s; + s << " BLUETOOTH_DEVICE_INFO:" << endl; + s << " dwSize: " << x.dwSize << endl; + s << " Address: " << ConvertAddress(x.Address) << endl; + s << " ulClassofDevice:" << x.ulClassofDevice << endl; + s << " fConnected: " << x.fConnected << endl; + s << " fRemembered: " << x.fRemembered << endl; + s << " fAuthenticated: " << x.fAuthenticated << endl; + s << " stLastSeen: " << tostring(x.stLastSeen) << " [GMT]" << endl; + s << " stLastUsed: " << tostring(x.stLastUsed) << " [GMT]" << endl; + s << " szName: " << ConvertName(x.szName) << endl; + return s.str(); +} + +string tostring(const BLUETOOTH_RADIO_INFO& x) +{ + FUNSTACK; + ostringstream s; + s << " PBLUETOOTH_RADIO_INFO:" << endl; + s << " dwSize: " << x.dwSize << endl; + s << " Address: " << ConvertAddress(x.address) << endl; + s << " szName: " << ConvertName(x.szName) << endl; + s << " ulClassofDevice:" << x.ulClassofDevice << endl; + s << " lmpSubversion: " << x.lmpSubversion << endl; + s << " manufacturer: " << x.manufacturer << endl; + return s.str(); +} + +bool USB_hub_updown(const bool up,const string& usbhub) +{ + FUNSTACK; + log << (up ? "Enabling" : "Disabling") << " 'USB hub..." << endl; + int n=-1; + System(string("devcon ") + (up ? "enable " : "disable ") + usbhub,false,false,&n); + if (n!=0) throw_("devcon failed, this can be to a erroneous usbhub string or if devcon.exe is not found in path, please install it from http://support.microsoft.com/kb/311272"); + log << "Done [OK]" << endl; + return true; +} + +int ScanforUSBmicrodevs() +{ + USBio io; + io.USBm_FindDevices(); + return io.Devices(); +} + +bool USB_microio_updown(const bool up,const bool dbg) +{ + FUNSTACK; + log << (up ? "Enabling" : "Disabling") << " USBm io..." << endl; + + // Discover the USBmicro devices + USBio io; + io.USBm_FindDevices(); + const int d=io.Devices(); + if (d==0) return false; // throw_("could not find an USBm device"); + else if (d>1) throw_("found more that one USBm devices"); + + static bool premable=true; + if (dbg && premable) { + premable=false; + log << " USBm info:" << endl << io.version(); + } + + io.USBm_InitPorts(0); + io.USBm_DirectionA(0, 0xff, 0xff); + + if(up) io.USBm_ResetBit(0,5); + else io.USBm_SetBit (0,5); + + log << "Done [OK]" << endl; + return true; +} + +bool __stdcall CloseDelcomhandle(HANDLE h){return DelcomCloseDevice(h)==0;} + +void do_cmd(HANDLE di, int ma, int mi, int lsb, int msb, unsigned char *data, unsigned datalen) +{ + //static struct delcom_packet p; + PacketStruct p; + memset(&p, 0, sizeof(p)); + p.MajorCmd = ma; + p.MinorCmd = mi; + p.DataLSB = lsb; + p.DataMSB = msb; + if (DelcomSendPacket(di,&p,&p)<0) throw_("DelcomSendPacket() failed"); +} + +int ScanforDelcomdevs() +{ + // Discover the USB Delcom devices + DeviceNameStruct names[10]; // array to hold the device names found + return DelcomScanDevices(USBIODS, names, 10); +} + +bool USB_delconio_updown(const bool up,const bool dbg) +{ + FUNSTACK; + log << (up ? "Enabling" : "Disabling") << " USB Delcom io..." << endl; + + DeviceNameStruct names[10]; // array to hold the device names found + const int d=DelcomScanDevices(USBIODS, names, 10); + if (d==0) return false; //throw_("could not find an USB Delcon device"); + else if (d>1) throw_("found more that one USB Delcon devices"); + + static bool premable=true; + if (dbg && premable) { + premable=false; + log << " USB Delcon info:" << (char*)&names[0] << "\n SN=" << DelcomReadDeviceSerialNum((char*)&names[0], NULL) << endl; + } + + DeviceAutoClose h(DelcomOpenDevice((char*)&names[0],0),CloseDelcomhandle); + if(up) do_cmd(h(),10,1,0xFE,0,0,0); + else do_cmd(h(),10,1,0xFF,0,0,0); + + log << "Done [OK]" << endl; + return true; +} + +bool USBupdown(const int iomode,const bool up,const bool dbg,const string& usbhub="") +{ + if (iomode==0) return true; + if (iomode==1) return USB_hub_updown(up,usbhub); + if (iomode==2) return USB_microio_updown(up,dbg); + else if (iomode==3) return USB_delconio_updown(up,dbg); + else throw_("bad io mode"); + return false; +} + +class Wiilib +{ + // Wiilib class based on wiiuse library by Michael Laforest. + // Library located at http://www.wiiuse.net + // Wiiuse premable from wiiuse_v0.12/example/example.c: + + // + // wiiuse + // + // Written By: + // Michael Laforest < para > + // Email: < thepara (--AT--) g m a i l [--DOT--] com > + // + // Copyright 2006-2007 + // + // This file is part of wiiuse. + // + // This program is free software; you can redistribute it and/or modify + // it under the terms of the GNU General Public License as published by + // the Free Software Foundation; either version 3 of the License, or + // (at your option) any later version. + // + // This program is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty of + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + // GNU General Public License for more details. + // + // You should have received a copy of the GNU General Public License + // along with this program. If not, see . + +private: + enum {MAX_WIIMOTES=1}; // use only one wiimote, but can connect to four + wiimote** m_wiimotes; + static int m_instantiations; + + int finddevices(const int wiitimeout,const bool rumble,const bool dbg) + { + FUNSTACK; + + // Find wiimote devices + const int to=wiitimeout/1000; + if (to<1) throw_("bad wiitimeout value, should be >=1000"); + const int found=wiiuse_find(m_wiimotes,MAX_WIIMOTES,to); + if (dbg) log << " wiiuse_find(0x0," << MAX_WIIMOTES << "," << to << ") return " << found << endl; + + if (found==0) { + if (dbg) log << " ** error: no wiimotes found" << endl; + return 0; + } + + // Connect to the wiimotes + assert(found>0); + + const int connected = wiiuse_connect(m_wiimotes, MAX_WIIMOTES); + if (connected==0){ + log << " ** error: could not connect to any wiimotes" << endl; + return 0; + } + if (dbg) log << " connected to " << connected<< " wiimotes (of " << MAX_WIIMOTES << " found)" << endl; + + + // Now set the LEDs and rumble for a second so it's easy + // to tell which wiimotes are connected (just like the wii does). + wiiuse_set_leds(m_wiimotes[0], WIIMOTE_LED_1); + + if (rumble){ + wiiuse_rumble(m_wiimotes[0], 1); + #ifndef WIN32 + usleep(200000); + #else + Sleep(200); + #endif + wiiuse_rumble(m_wiimotes[0], 0); + } + + // read some data to be sure of connection + for(int i=0;i<8;++i){ + Sleep(50); + + int led=0; + switch(i%6){ + case 0 : led=WIIMOTE_LED_1; break; + case 1 : led=WIIMOTE_LED_2; break; + case 2 : led=WIIMOTE_LED_3; break; + case 3 : led=WIIMOTE_LED_4; break; + case 4 : led=WIIMOTE_LED_3; break; + case 5 : led=WIIMOTE_LED_2; break; + } + wiiuse_rumble(m_wiimotes[0], 0); // to be sure + wiiuse_set_leds(m_wiimotes[0],led); + wiiuse_status(m_wiimotes[0]); + if (led!=m_wiimotes[0]->leds) throw_("bad LED status on wiimote, is it connected properly?"); + } + + // set all leds, retry a couple of time to be sure + for(int i=0;i<4;++i){ + wiiuse_set_leds(m_wiimotes[0],WIIMOTE_LED_1 | WIIMOTE_LED_2 | WIIMOTE_LED_3 | WIIMOTE_LED_4); + Sleep(100); + } + + return connected; + } + + Wiilib() : m_wiimotes(0) + { + FUNSTACK; + if (m_instantiations!=0) throw_("can only instatiate one Wiilib at a time"); + ++m_instantiations; // assumes a single-thread application, else we have a race condition here + + // Initialize an array of wiimote objects. + // The parameter is the number of wiimotes I want to create. + m_wiimotes = wiiuse_init(MAX_WIIMOTES); + // wiiuse_set_bluetooth_stack(m_wiimotes, MAX_WIIMOTES,WIIUSE_STACK_MS); must be done automatically + assert(m_instantiations==1); + } + + ~Wiilib() + { + FUNSTACK; + assert( m_instantiations==1 ); + + // Disconnect the wiimotes + if (m_wiimotes!=0) wiiuse_cleanup(m_wiimotes, MAX_WIIMOTES); + m_wiimotes=0; + --m_instantiations; + assert(m_instantiations==0); + } + + static int OpenDevices_wiilib(const int wiitimeout,const bool rumble,const bool dbg,const bool precheck=false) + { + FUNSTACK; + int n=0,retries=0; + while(n==0 && retries++<10) { + n=Wiilib().finddevices(wiitimeout,rumble,dbg); + if (precheck) break; + if (n==0) { + if (dbg) log << " OpenDevice()...delaying " << (retries<5 ? "250" : "1000") << " [ms]" << endl; + if (retries<5) Sleep(250); + else Sleep(1000); + } + } + if (dbg) {cerr.flush(); log << " Wiilib::OpenDevice..." << n << endl;} + return n; + } + + static int OpenDevices_wiimotelib(const int wiitimeout,const bool rumble,const bool dbg,const bool precheck=false) + { + FUNSTACK; + int n=0,retries=0; + while(n==0 && retries++<10) { + n=system("wiimotelibpoll")==0 ? 1 : 0; + if (precheck) break; + if (n==0) { + if (dbg) log << " OpenDevice()...delaying " << (retries<5 ? "250" : "1000") << " [ms]" << endl; + if (retries<5) Sleep(250); + else Sleep(1000); + } + } + if (dbg) {cerr.flush(); log << " Wiilib::OpenDevice..." << n << endl;} + return n; + } + +public: + + static int OpenDevices(const string& wiilib,const int wiitimeout,const bool rumble,const bool dbg,const bool precheck=false) + { + FUNSTACK; + if (wiilib=="wiiuse") return OpenDevices_wiilib(wiitimeout,rumble,dbg,precheck); + else if (wiilib=="wiimotelib") return OpenDevices_wiimotelib(wiitimeout,rumble,dbg,precheck); + else if (wiilib=="none") return -1; + else throw_("Wiilib::OpenDevices(), library must be one-of {wiiuse,wiimotelib,none}"); + return -1; // avoid compiler error + } + +}; + +int Wiilib::m_instantiations=0; + +BLUETOOTH_DEVICE_SEARCH_PARAMS Get_BLUETOOTH_DEVICE_SEARCH_PARAMS(const int timeout) +{ + FUNSTACK; + BLUETOOTH_DEVICE_SEARCH_PARAMS b; + ZeroMemory(&b, sizeof(b)); + b.dwSize = sizeof(b); + b.fReturnAuthenticated = TRUE; + b.fReturnRemembered = TRUE; + b.fReturnUnknown = TRUE; + b.fReturnConnected = TRUE; + b.fIssueInquiry = TRUE; + + const int to=static_cast(1.0*timeout/1000.0/1.28+0.5); + assert(to>=0 && to<48 ); + b.cTimeoutMultiplier = (to==0 ? 1 : to); // timeout of 0 causes havac + b.hRadio = NULL; + + assert( b.cTimeoutMultiplier>0 ); + return b; +} + +BLUETOOTH_DEVICE_INFO Get_BLUETOOTH_DEVICE_INFO() +{ + FUNSTACK; + BLUETOOTH_DEVICE_INFO b; + ZeroMemory(&b, sizeof(b)); + b.dwSize = sizeof(b); + return b; +} + +BLUETOOTH_RADIO_INFO Get_BLUETOOTH_RADIO_INFO() +{ + FUNSTACK; + BLUETOOTH_RADIO_INFO b; + ZeroMemory(&b, sizeof(b)); + b.dwSize = sizeof(b); + return b; +} + +BLUETOOTH_FIND_RADIO_PARAMS Get_BLUETOOTH_FIND_RADIO_PARAMS() +{ + FUNSTACK; + BLUETOOTH_FIND_RADIO_PARAMS b; + ZeroMemory(&b, sizeof(b)); + b.dwSize = sizeof(b); + return b; +} + +bool ReachedMax(const int i) +{ + FUNSTACK; + if (i>MAX_DEVICE_COUNT) { + log << " ** warning: too many devices found, can only handle " << MAX_DEVICE_COUNT << " devices" << endl; + return true; + } + return false; +} + +bool RemoveDev(const BLUETOOTH_DEVICE_INFO& bdi) +{ + FUNSTACK; + DWORD status=BluetoothUpdateDeviceRecord(&bdi); + if (status!=ERROR_SUCCESS) throw_("BluetoothUpdateDeviceRecord() failed"); + + status=BluetoothRemoveDevice(&bdi.Address); + if (status==ERROR_SUCCESS) log << " removed device successfully..." << endl << "Done [OK]" << endl; + else log << " ** error: removing the device failed, was it registred at all?" << endl <<"Done [FAILED]" << endl; + + return status==ERROR_SUCCESS; +} + +HANDLE RadioInfo(const string& btr,const bool dbg) +{ + FUNSTACK; + if (dbg) log << " Radio info" << endl; + assert( btr.size()==17 || btr.size()==0 || btr=="all"); + + HANDLE hRadio=NULL; + BLUETOOTH_FIND_RADIO_PARAMS btfrp=Get_BLUETOOTH_FIND_RADIO_PARAMS(); + DeviceAutoClose hbf(BluetoothFindFirstRadio(&btfrp,&hRadio),&BluetoothFindRadioClose); + + if (hbf()==NULL) { + if (dbg) log << " " << endl; + return NULL; + } + + while(hbf()!=NULL){ + if (hbf()==NULL) throw_("BluetoothFindFirstRadio() failed"); + + BLUETOOTH_RADIO_INFO r=Get_BLUETOOTH_RADIO_INFO(); + if (BluetoothGetRadioInfo(hRadio,&r)!=ERROR_SUCCESS) throw_("BluetoothGetRadioInfo() failed"); + + const int c=BluetoothIsConnectable(hRadio); + const int d=BluetoothIsDiscoverable(hRadio); + + if (dbg){ + log << indent(tostring(r)," "); + log << " connectable: " << c << endl; + log << " discoverabel: " << d << endl; + } + + if (btr.size()==0) break; + else if (btr==ConvertAddress(r.address)){ + if (dbg) log << " found radio address match " << (btr.size()>0 ? ": " + btr : "") << endl; + break; + } + + if (!BluetoothFindNextRadio(&btfrp,&hRadio)) break; + } + + if (dbg) log << "Done [" << (hRadio==NULL ? "FAILED" : "OK") << "]" << endl; + return hRadio; +} + +bool ScanDevices(const int timeout) +{ + FUNSTACK; + log << "Scanning devices" << endl; + + vector infos; + + BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp=Get_BLUETOOTH_DEVICE_SEARCH_PARAMS(timeout); + BLUETOOTH_DEVICE_INFO bdi=Get_BLUETOOTH_DEVICE_INFO(); + + DeviceAutoClose hbf(BluetoothFindFirstDevice(&bdsp,&bdi),&BluetoothFindDeviceClose); + const DWORD dwErr = GetLastError(); + + if (hbf()==NULL) { + log << " ** warning: no devices found" << endl << "Done [FAILED]" << endl; + return false;; + } + + if (hbf()!= NULL) { + log << "Looking for devices..." << endl; + + int i=0; + while(1){ + if (ReachedMax(i)) break; + + const string t=ConvertName(bdi.szName); + log << " found device [" << i << "]: <" << (t.size()>0 ? t : "NONAME") << ">" << endl; + + infos.push_back(bdi); + + if (BluetoothFindNextDevice(hbf(), &bdi) == FALSE) + break; + + ++i; + } + } + + log << "BTDevices info:" << endl; + if (infos.size()==0) log << " " << endl; + else for(size_t i=0;i0 ? s : "") << endl; + log << tostring(t); + } + log << "Done [OK]" << endl; + + return true; +} + +bool RemoveDevice(const string& d,const bool dbg) +{ + FUNSTACK; + log << "Removing device <" << d << ">" << endl; + + BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp=Get_BLUETOOTH_DEVICE_SEARCH_PARAMS(1); // timout must be greater than zero, eventhough I only return remembered devices! + BLUETOOTH_DEVICE_INFO bdi=Get_BLUETOOTH_DEVICE_INFO(); + + bdsp.fReturnAuthenticated = FALSE; + bdsp.fReturnRemembered = TRUE; + bdsp.fReturnUnknown = FALSE; + bdsp.fReturnConnected = TRUE; + + DeviceAutoClose hbf(BluetoothFindFirstDevice(&bdsp,&bdi),&BluetoothFindDeviceClose); + + const DWORD dwErr = GetLastError(); + + if (hbf()==NULL) { + log << " ** error: failed to find device" << endl << "Done [FAILED]" << endl; + return false; + } + + int i=0; + while(true){ + if (ReachedMax(i)) break; + const string fd=ConvertName(bdi.szName); + log << " found device [" << i << "]: <" << (fd.size()>0 ? fd : "NONAME") << ">" << endl; + + if (fd==d){ + log << " found match..." << endl; + log << " trying to remove..." << endl; + + return RemoveDev(bdi); + } + if (BluetoothFindNextDevice(hbf(), &bdi) == FALSE) break; + ++i; + } + log << " ** error: failed to find device" << endl << "Done [FAILED]" << endl; + return false; +} + +bool MatchAdr(const string& pattern,const string& adr) +{ + assert(pattern.size()==17 && adr.size()==17); + for(size_t i=0;i<17;++i){ + if (!(pattern[i]=='?' || pattern[i]==adr[i])) return false; + } + return true; +} + +bool MatchDevice(const string& d,const vector& known_adr,const BLUETOOTH_DEVICE_INFO& bdi,const bool dbg) +{ + FUNSTACK; + + const string found_adr=ConvertAddress(bdi.Address); + bool wildcard=false; + for(size_t i=0;i(p); + assert(p!=0 && q->done==false && q->timeout>0 && q->hbf==0 ); + + BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp=Get_BLUETOOTH_DEVICE_SEARCH_PARAMS(q->timeout); + + q->hbf=BluetoothFindFirstDevice(&bdsp,&q->bdi); + const DWORD status=GetLastError(); + + if (status==ERROR_INVALID_PARAMETER) throw_("BluetoothFindFirstDevice(), returned status=ERROR_INVALID_PARAMETER"); + else if (status==ERROR_REVISION_MISMATCH) throw_("BluetoothFindFirstDevice(), returned status=ERROR_REVISION_MISMATCH"); + + q->done=true; + return 0; +} + +bool OpenDevice(const string& d,const string& btr,const int timeout,const int wiitimeout,const vector& known_adr,const int btsleep,const string& lib,const bool precheckwiimotes,const bool rumble,const bool dbg,bool& invalidargflag) +{ + FUNSTACK; + assert( invalidargflag==false ); + log << "Open device <" << d << ">" << endl; + + if (precheckwiimotes && Wiilib::OpenDevices(lib,wiitimeout,false,dbg,true)>=1) { + log << " service is already opened..." << endl << "Done [OK]" << endl; + return true; + } + + if (dbg && known_adr.size()>0) { + log << " known addresses="; + for(size_t i=0;i hbf(BluetoothFindFirstDevice(&bdsp,&bdi),&BluetoothFindDeviceClose); + // + // FIX: start the BluetoothFindFirstDevice() function in a thread, terminate the thread if it has run for longer than, say 2+timeout. + // + // Old code: + // BLUETOOTH_DEVICE_SEARCH_PARAMS bdsp=Get_BLUETOOTH_DEVICE_SEARCH_PARAMS(timeout); + // BLUETOOTH_DEVICE_INFO bdi=Get_BLUETOOTH_DEVICE_INFO(); + // DeviceAutoClose hbf(BluetoothFindFirstDevice(&bdsp,&bdi),&BluetoothFindDeviceClose); + // DWORD status=GetLastError(); + + unsigned long tid=0; + DeviceAutoClose h(CreateThread(0,0,BluetoothFindFirstDevice_thread,&p,0,&tid),CloseHandle); + timer tthread; + + Sleep(timeout); + while(!p.done && tthread.elapsed()*1000<2*timeout) Sleep(20); // or use WaitForMultipleObjects(...); + } + + if(!p.done){ + log << " ** error: BluetoothFindFirstDevice() stalled" << endl<< "Done [FAILED]" << endl; + return false; + } + else if(p.hbf==0){ + log << " ** error: BluetoothFindFirstDevice() returned null hbf" << endl<< "Done [FAILED]" << endl; + return false; + } + + assert(p.hbf!=0); + BLUETOOTH_DEVICE_INFO bdi=p.bdi; + DeviceAutoClose hbf(p.hbf,&BluetoothFindDeviceClose); + + if (hbf()==NULL) { + log << " ** error: no devices found" << endl << "Done [FAILED]" << endl; + return false; + } + + int i=0; + while(true){ + if (ReachedMax(i)) break; + const string fd=ConvertName(bdi.szName); + log << " found device [" << i << "]: <" << (fd.size()>0 ? fd : "NONAME") << ">" << endl; + + if (MatchDevice(d,known_adr,bdi,dbg)){ + log << " found match..." << endl; + if (dbg) log << tostring(bdi); + + // write binary dbi, test code for now + //ofstream ox("bdi.out",ios::binary); + //ox.write(reinterpret_cast(&bdi),sizeof(bdi)); + + log << " trying to open..." << endl; + DWORD status=BluetoothUpdateDeviceRecord(&bdi); + if (status!=ERROR_SUCCESS) throw_("BluetoothUpdateDeviceRecord() failed"); + if (dbg) log << " BluetoothUpdateDeviceRecord()...OK" << endl; + + { + DeviceAutoClose hRadio(RadioInfo(btr,dbg),&CloseHandle); + if (hRadio()==NULL) throw_("failed to get radio"); + if (dbg) log << " RadioInfo()...OK" << endl; + + const GUID service=HumanInterfaceDeviceServiceClass_UUID; + status=BluetoothSetServiceState(hRadio(),&bdi,&service,BLUETOOTH_SERVICE_ENABLE); + + if (dbg && status==ERROR_SUCCESS) log << " BluetoothSetServiceState()...OK" << endl; + if (dbg && status!=ERROR_SUCCESS) log << " BluetoothSetServiceState()...ERROR" << endl; + } + + if (status!=ERROR_SUCCESS) { + string t; + if (status==ERROR_INVALID_PARAMETER) t="ERROR_INVALID_PARAMETER"; + else if (status==ERROR_SERVICE_DOES_NOT_EXIST) t="ERROR_SERVICE_DOES_NOT_EXIST"; + else if (status==E_INVALIDARG) t="E_INVALIDARG"; + // if (status!=E_INVALIDARG) throw_("BluetoothSetServiceState() failed with errorcode " + t); + // else log << " ** error: BluetoothSetServiceState() returned " << t << endl; + + if (status==E_INVALIDARG) invalidargflag=true; + log << " ** error: BluetoothSetServiceState() returned " << t << endl; + log << endl << "Done [FAILED]" << endl; + return false; + } + + // sleep while windows slowly does strange things + Sleep(btsleep); + + if (lib!="none") + { + if (Wiilib::OpenDevices(lib,wiitimeout,rumble,dbg)==0) { + log << " ** error: service could not be opened..." << endl<< "Done [FAILED]" << endl; + return false; + } + } + + log << " service on device enabled..." << endl << " opended device successfully..." << endl << "Done [OK]" << endl; + return true; + } + + if (BluetoothFindNextDevice(hbf(), &bdi) == FALSE) break; + ++i; + } + log << " ** error: device not mathced" << endl<< "Done [FAILED]" << endl; + return false; +} + +bool AutoOpenDevice(const string& d,const string& btr,const int timeout,const int wiitimeout,const int usbsleep,const int btsleep,const int usbmsleep,const string& cf,const string& lib,const int removemode,const int usbmode,const bool wb,const int scanretries,const bool dbg,bool& invalidargflag) +{ + FUNSTACK; + + int cl=0; + if (g_automode_callback==0) g_automode_callback=&DummyCallback; + + if (usbmode==2 && ScanforUSBmicrodevs()!=1) { + log << "Could not find any USBm devices" << endl << "Wiiscan done [FAILED]" << endl; + return false; + } + if (usbmode==3 && ScanforDelcomdevs()!=1) { + log << "Could not find any Delcom devices" << endl << "Wiiscan done [FAILED]" << endl; + return false; + } + + g_automode_callback(cl++); + + timer total; + assert(usbsleep>=0 && btsleep>=0 && usbmsleep>=0); + + log << "Auto-connecting to device <" << d << ">" << endl; + + // check valid config file + if (!FileExists(cf)) throw_("config file <" + cf + "> is missing"); + const Configfile c(cf); + if (dbg) log << c; + if (!c.hasEntry("all_usb_hubs")) throw_("config file missing entry"); + if (!c.hasEntry("active_usb_hub")) throw_("config file missing entry"); + if (!c.hasEntry("allowed_wiimote_adr")) throw_("config file missing entry"); + if (!c.hasEntry("whiteboard_software")) throw_("config file missing entry"); + + // test if already opened + g_automode_callback(cl++); + + if (removemode==0 && Wiilib::OpenDevices(lib,wiitimeout,false,dbg,true)>=1) { + log << " service is already opened..." << endl << "Done [OK]" << endl; + + if (wb){ + // fireup whiteboard software + if (!c.hasEntry("whiteboard_software")) log << " ** warning: config file is missing entry " << endl; + else System(c.Get("whiteboard_software",true),false,false); + } + + return true; + } + + // power down now if using USB io board + g_automode_callback(cl++); + USBupdown(usbmode,false,dbg); + timer t; + + // remove old entries in HID + g_automode_callback(cl++); + if(removemode!=2) RemoveDevice(d,dbg); + + // Cycle usb hub, turn off usb power and restart the wiimote + g_automode_callback(cl++); + if(usbmode==1){ + const string usbhub=c.Get("active_usb_hub"); + if(usbhub!="\"\""){ + USBupdown(usbmode,false,dbg,usbhub); + Sleep(usbsleep); + USBupdown(usbmode,true,dbg,usbhub); + + g_automode_callback(cl++); + + // wait for usb hub to be up, takes some seconds (1000ms to 2000ms approx) + Sleep(1800); + + // wait for usb radio to be ready + g_automode_callback(cl++); + HANDLE hRadio=RadioInfo(btr,dbg); + + int i=0; + while(hRadio==NULL) { + if (i++==0) log << " radio not ready, delaying."; + else log << "."; + Sleep(500); + hRadio=RadioInfo(btr,dbg); + if (i>10) throw_("could not connect to bluetooth radio device"); + } + CloseHandle(hRadio); + if (i>0) log << endl; + } + } else if (usbmode!=0) { + while (t.elapsed()*1000=1 ); + while(!openok && ++retries<=scanretries){ + openok=OpenDevice(d,btr,min(retries*timeout,8000),wiitimeout,c("allowed_wiimote_adr"),btsleep,lib,false,false,dbg,invalidargflag); + } + + if (openok){ + g_automode_callback(cl++); + if (wb){ + g_automode_callback(cl++); + // terminate running wb's + + // fireup whiteboard software + if (!c.hasEntry("whiteboard_software")) log << " ** warning: config file is missing entry " << endl; + else System(c.Get("whiteboard_software",true),false,false); + } + } + if (dbg) log << " Elapsed time: " << total.elapsed() << " [s]" << endl; + + // taking longer than 20 sec will bring up an annoying windows reboot dialog, + // that can be ignored, hence warn at 18 sec + if (total.elapsed()>18) log << " ** warning: connection took a long time to finish, this may cause a windows reboot dialog, that can be ignored" << endl; + + if (!openok) log << " ** warning: could not open device" << endl << "Done [FAILED]" << endl; + + assert(cl<10); + g_automode_callback(42); + return openok; +} + +int Usage(const args& arg,const string msg="") +{ + FUNSTACK; + if (msg.size()>0) log << msg << endl; + log << "Usage: " << arg[0] << " <-a | -c | -d | -r | -s | -usbup | -usbdown> [-cf ] [-lf ] [-b ] [-t ] [-u ] [-p ] [-w ] [-q ] [-f ] [-m ] [-l ] [-y] [-wb] [-v] " << endl; + log << " " << Version() << " " << Config() << endl; + log << " modes:" << endl; + log << " -a : autoconnect to device" << endl; + log << " -c : connect the device, that matches this name" << endl; + log << " -d : deletes the device, that matches this name" << endl; + log << " -r: lookup and list bluetooth radio devices" << endl; + log << " -s: scan external bluetooth devices" << endl; + log << " -usbdown: disable usb hubs" << endl; + log << " -usbup: enable usb hubs" << endl; + log << " options:" << endl; + log << " -cf : specify a distinct configurationfile, default=" << DEFAULT_configfile << endl; + log << " -lf : specify a distinct logfile, default=" << DEFAULT_logfile << endl; + log << " -b : automode bluetooth connection sleep in milliseconds, default=" << DEFAULT_btsleep << endl; + log << " -t : timeout for bluetooth stack in milliseconds, default=" << DEFAULT_timeout << endl; + log << " -u : automode usb connection sleep in milliseconds, default=" << DEFAULT_usbsleep << endl; + log << " -p : automode usbm post-connection sleep in milliseconds, default=" << DEFAULT_usbmsleep << endl; + log << " -w : timeout for wiimote in milliseconds, default=" << DEFAULT_wiitimeout << endl; + log << " -q : use bluetooth radio with this address (not working), default=any device" << endl; + log << " -f : pre-remove mode of device, 0=remove if not connectable, 1=always remove, 2=never remove, default=" << DEFAULT_removemode << endl; + log << " -m : choose USB powercycle mode, 0=no power cycle, 1=use USB hub, 2=use USBm IO hardware, 3=use USB Delcon IO hardware" << endl; + log << " -l : use specific wiimote library, lib can be one-of {wiiuse,wiimotelib, default=" << DEFAULT_wiilib << endl; + log << " -y : scan retries in automode, default=" << DEFAULT_scanretries<< endl; + log << " -wb: start whiteboard in automode" << endl; + log << " -nowb: do not start whiteboard in automode" << endl; + log << " -v: enable extra debugging printouts" << endl; + log << " default mode: -a \"" << NINTENDO_DEV << "\"" << endl; + log << " note: \"nintendo\" is a shortcut for \"" << NINTENDO_DEV << "\"" << endl; + return -1; +} + +int main(int argc,char** argv) +{ + FUNSTACK; + bool invalidargflag=false; + try{ + SetNiceLevel(-15); // set to time-critical + args arg(argc,argv); + + // first, parse the command line configfile, then load the config, finally override any configfile options with given command line options + string cf=arg.parseval("-cf",DEFAULT_configfile); + + bool v=false,wb=false; + int timeout =DEFAULT_timeout; + int wiitimeout=DEFAULT_wiitimeout; + int usbsleep =DEFAULT_usbsleep; + int usbmsleep =DEFAULT_usbmsleep; + int btsleep =DEFAULT_btsleep; + int usbmode =DEFAULT_usbmode; + int removemode=DEFAULT_removemode; + int scanretries=DEFAULT_scanretries; + string a,c,d,btr,lf=DEFAULT_logfile,dev=NINTENDO_DEV,lib=DEFAULT_wiilib; + + if (FileExists(cf)){ + const Configfile cnf(cf); + if (cnf.hasEntry("option_device")) dev=strip(cnf.Get("option_device"),'"'); + if (cnf.hasEntry("option_timeout")) timeout=cnf.Get("option_timeout"); + if (cnf.hasEntry("option_wiitimeout")) wiitimeout=cnf.Get("option_wiitimeout"); + if (cnf.hasEntry("option_usbsleep")) usbsleep=cnf.Get("option_usbsleep"); + if (cnf.hasEntry("option_usbmsleep")) usbmsleep=cnf.Get("option_usbmsleep"); + if (cnf.hasEntry("option_btsleep")) btsleep=cnf.Get("option_btsleep"); + if (cnf.hasEntry("option_usbpowermode")) usbmode=cnf.Get("option_usbpowermode"); + if (cnf.hasEntry("option_removemode")) removemode=cnf.Get("option_removemode"); + if (cnf.hasEntry("option_debug")) v=cnf.Get("option_debug"); + if (cnf.hasEntry("option_startwhiteboard")) wb=cnf.Get("option_startwhiteboard"); + if (cnf.hasEntry("option_logfile")) lf=cnf.Get("option_logfile"); + if (cnf.hasEntry("option_btradio")) btr=cnf.Get("option_btradio"); + if (cnf.hasEntry("option_wiilib")) lib=cnf.Get("option_wiilib"); + if (cnf.hasEntry("option_scanretries"))scanretries=cnf.Get("option_scanretries"); + } + + // parse argumets via args class + const bool r=arg.parseopt("-r"); + const bool s=arg.parseopt("-s"); + const bool u=arg.parseopt("-?"); + const bool usbdown=arg.parseopt("-usbdown"); + const bool usbup=arg.parseopt("-usbup"); + v=arg.parseopt("-v") || v; + wb=arg.parseopt("-wb") || wb; + wb=!arg.parseopt("-nowb") && wb; + timeout =arg.parseval("-t",timeout); + wiitimeout=arg.parseval("-w",wiitimeout); + usbsleep =arg.parseval("-u",usbsleep); + usbmsleep =arg.parseval("-p",usbmsleep); + btsleep =arg.parseval("-b",btsleep); + usbmode =arg.parseval("-m",usbmode); + removemode=arg.parseval("-f",removemode); + a=arg.parseval("-a",""); + c=arg.parseval("-c",""); + d=arg.parseval("-d",""); + lf=arg.parseval("-lf",lf); + btr=arg.parseval("-q",btr); + lib=arg.parseval("-l",lib); + scanretries=arg.parseval("-y",scanretries); + + if (arg.size()!=1) return Usage(arg); + + // apply shortcuts + if (a=="nintendo") a=dev; + if (c=="nintendo") c=dev; + if (d=="nintendo") d=dev; + + // open log file before Usage call + if(lf!=DEFAULT_logfile){ + lf=strip(lf,'"'); // cannot handle filenames in citation quotes + if (lf=="cout" || lf=="std::cout") g_log=&cout; + else if (lf=="cerr" || lf=="std::cerr") g_log=&cerr; + else { + g_log.open(lf,ios_base::app); + g_log.writelogheader("Wiiscan::main()"); + if (v) log << "Using logfile <" << lf << ">" << endl; + } + } + + const int check=(r ? 1 : 0)+ (s ? 1 : 0) + (a.size()>0 ? 1 : 0) + (c.size()>0 ? 1 : 0) + (d.size()>0 ? 1 : 0) + usbup + usbdown; + if (check>1 || u) return Usage(arg); + + if (timeout<20) throw_("bad value of timeout, should be >=20"); + if (wiitimeout<20)throw_("bad value of wiitimeout, should be >=20"); + if (usbsleep<20) throw_("bad value of usbsleep, should be >=20"); + if (usbmsleep<20) throw_("bad value of usbmsleep, should be >=20"); + if (btsleep<20) throw_("bad value of btsleep, should be >=20"); + if (usbdown && usbup) throw_("bad value of usbdown/up, cannot be used at the same time"); + if (wiitimeout%1000!=0) throw_("bad value, wiitimeout should be divisable with 1000"); + if (btr.size()>0 && btr.size()!=17) throw_("bluetooth radio must be in the form xx:xx:xx:xx:xx:xx"); + if (usbmode<0 || usbmode>3) throw_("bad usbpowermode, must be 0,1,2, or 3"); + if (removemode<0 || removemode>2) throw_("bad removemode, must be 0,1 or 2"); + if (scanretries<=0) throw_("bad value of scanretries, should be > 0"); + if (a.size()==0) a=NINTENDO_DEV; + + if (v) { + log << Version() << " " << Config() << endl; + log << "Values:" << endl; + log << " a=" << a << endl; + log << " c=" << c << endl; + log << " d=" << d << endl; + log << " r=" << r << endl; + log << " s=" << s << endl; + log << " v=" << v << endl; + log << " cf=" << cf << endl; + log << " lf=" << lf << endl; + log << " wb=" << wb << endl; + log << " btr=" << btr << endl; + log << " lib=" << lib << endl; + log << " usbmode=" << usbmode << endl; + log << " removemode=" << removemode << endl; + log << " scanretries=" << scanretries << endl; + log << " usbup =" << usbup << endl; + log << " usbdown=" << usbup << endl; + log << "Timeouts:" << endl; + log << " timeout =" << timeout << endl; + log << " wiitimeout=" << wiitimeout << endl; + log << " usbsleep =" << usbsleep << endl; + log << " usbmsleep =" << usbmsleep << endl; + log << " btsleep =" << btsleep << endl; + } + + bool ret=true; + + if (r) ret=RadioInfo (btr.size()==0 ? "all" : btr,v)!=NULL; + else if (s) ret=ScanDevices (timeout); + else if (c.size()>0) ret=OpenDevice (c,btr,timeout,wiitimeout,vector(),btsleep,lib,true,true,v,invalidargflag); + else if (d.size()>0) ret=RemoveDevice(d,v); + else if (usbup) ret=USBupdown (usbmode,true, v,Configfile(cf).Get("active_usb_hub",true)); + else if (usbdown) ret=USBupdown (usbmode,false,v,Configfile(cf).Get("active_usb_hub",true)); + else ret=AutoOpenDevice(a,btr,timeout,wiitimeout,usbsleep,btsleep,usbmsleep,cf,lib,removemode,usbmode,wb,scanretries,v,invalidargflag); // default mode + + log << "Wiiscan done " << (ret ? "[OK]" : "[FAILED]") << endl; + + if (invalidargflag) { + if (v) log << "** warning: return=-3 (E_INVALIDARG)" << endl; + return -3; + } + + if (v) log << "returning: return=" << (ret ? "0" : "-1") << endl; + return ret ? 0 : -1; // 0=Ok, -1=fail, -2=fail with exception, -3=fail with E_INVALIDARG + } + CATCH_ALL; + + assert(invalidargflag==false); // flag not setted => no throw in when E_INVALIDARG encoutered + log << "Wiiscan done [FAILED]" << endl; + return -2; +} + +}; // namespace Wiiscan diff --git a/src/main/headers/wiiuse.h b/src/main/headers/wiiuse.h new file mode 100644 index 0000000..9dff81c --- /dev/null +++ b/src/main/headers/wiiuse.h @@ -0,0 +1,653 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * $Header$ + * + */ + +/** + * @file + * + * @brief API header file. + * + * If this file is included from inside the wiiuse source + * and not from a third party program, then wiimote_internal.h + * is also included which extends this file. + */ + +#ifndef WIIUSE_H_INCLUDED +#define WIIUSE_H_INCLUDED + +#ifdef _WIN32 + /* windows */ + #include +#else + /* nix */ + #include +#endif + +#ifdef WIIUSE_INTERNAL_H_INCLUDED + #define WCONST +#else + #define WCONST const +#endif + +/* led bit masks */ +#define WIIMOTE_LED_NONE 0x00 +#define WIIMOTE_LED_1 0x10 +#define WIIMOTE_LED_2 0x20 +#define WIIMOTE_LED_3 0x40 +#define WIIMOTE_LED_4 0x80 + +/* button codes */ +#define WIIMOTE_BUTTON_TWO 0x0001 +#define WIIMOTE_BUTTON_ONE 0x0002 +#define WIIMOTE_BUTTON_B 0x0004 +#define WIIMOTE_BUTTON_A 0x0008 +#define WIIMOTE_BUTTON_MINUS 0x0010 +#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020 +#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040 +#define WIIMOTE_BUTTON_HOME 0x0080 +#define WIIMOTE_BUTTON_LEFT 0x0100 +#define WIIMOTE_BUTTON_RIGHT 0x0200 +#define WIIMOTE_BUTTON_DOWN 0x0400 +#define WIIMOTE_BUTTON_UP 0x0800 +#define WIIMOTE_BUTTON_PLUS 0x1000 +#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000 +#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000 +#define WIIMOTE_BUTTON_UNKNOWN 0x8000 +#define WIIMOTE_BUTTON_ALL 0x1F9F + +/* nunchul button codes */ +#define NUNCHUK_BUTTON_Z 0x01 +#define NUNCHUK_BUTTON_C 0x02 +#define NUNCHUK_BUTTON_ALL 0x03 + +/* classic controller button codes */ +#define CLASSIC_CTRL_BUTTON_UP 0x0001 +#define CLASSIC_CTRL_BUTTON_LEFT 0x0002 +#define CLASSIC_CTRL_BUTTON_ZR 0x0004 +#define CLASSIC_CTRL_BUTTON_X 0x0008 +#define CLASSIC_CTRL_BUTTON_A 0x0010 +#define CLASSIC_CTRL_BUTTON_Y 0x0020 +#define CLASSIC_CTRL_BUTTON_B 0x0040 +#define CLASSIC_CTRL_BUTTON_ZL 0x0080 +#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200 +#define CLASSIC_CTRL_BUTTON_PLUS 0x0400 +#define CLASSIC_CTRL_BUTTON_HOME 0x0800 +#define CLASSIC_CTRL_BUTTON_MINUS 0x1000 +#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000 +#define CLASSIC_CTRL_BUTTON_DOWN 0x4000 +#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000 +#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF + +/* guitar hero 3 button codes */ +#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001 +#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008 +#define GUITAR_HERO_3_BUTTON_GREEN 0x0010 +#define GUITAR_HERO_3_BUTTON_BLUE 0x0020 +#define GUITAR_HERO_3_BUTTON_RED 0x0040 +#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080 +#define GUITAR_HERO_3_BUTTON_PLUS 0x0400 +#define GUITAR_HERO_3_BUTTON_MINUS 0x1000 +#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000 +#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF + + +/* wiimote option flags */ +#define WIIUSE_SMOOTHING 0x01 +#define WIIUSE_CONTINUOUS 0x02 +#define WIIUSE_ORIENT_THRESH 0x04 +#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH) + +#define WIIUSE_ORIENT_PRECISION 100.0f + +/* expansion codes */ +#define EXP_NONE 0 +#define EXP_NUNCHUK 1 +#define EXP_CLASSIC 2 +#define EXP_GUITAR_HERO_3 3 + +/* IR correction types */ +typedef enum ir_position_t { + WIIUSE_IR_ABOVE, + WIIUSE_IR_BELOW +} ir_position_t; + +/** + * @brief Check if a button is pressed. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_PRESSED(dev, button) ((dev->btns & button) == button) + +/** + * @brief Check if a button is being held. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is held, 0 if not. + */ +#define IS_HELD(dev, button) ((dev->btns_held & button) == button) + +/** + * @brief Check if a button is released on this event. \n\n + * This does not mean the button is not pressed, it means \n + * this button was just now released. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is released, 0 if not. + * + */ +#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button) + +/** + * @brief Check if a button has just been pressed this event. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button)) + +/** + * @brief Return the IR sensitivity level. + * @param wm Pointer to a wiimote_t structure. + * @param lvl [out] Pointer to an int that will hold the level setting. + * If no level is set 'lvl' will be set to 0. + */ +#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \ + do { \ + if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \ + else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \ + else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \ + else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \ + else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \ + else *lvl = 0; \ + } while (0) + +#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020) +#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040) +#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080) +#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100) + +#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num) + +/* + * Largest known payload is 21 bytes. + * Add 2 for the prefix and round up to a power of 2. + */ +#define MAX_PAYLOAD 32 + +/* + * This is left over from an old hack, but it may actually + * be a useful feature to keep so it wasn't removed. + */ +#ifdef WIN32 + #define WIIMOTE_DEFAULT_TIMEOUT 10 + #define WIIMOTE_EXP_TIMEOUT 10 +#endif + +typedef unsigned char byte; +typedef char sbyte; + +struct wiimote_t; +struct vec3b_t; +struct orient_t; +struct gforce_t; + + +/** + * @brief Callback that handles a read event. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Pointer to the filled data block. + * @param len Length in bytes of the data block. + * + * @see wiiuse_init() + * + * A registered function of this type is called automatically by the wiiuse + * library when the wiimote has returned the full data requested by a previous + * call to wiiuse_read_data(). + */ +typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len); + + +/** + * @struct read_req_t + * @brief Data read request structure. + */ +struct read_req_t { + wiiuse_read_cb cb; /**< read data callback */ + byte* buf; /**< buffer where read data is written */ + unsigned int addr; /**< the offset that the read started at */ + unsigned short size; /**< the length of the data read */ + unsigned short wait; /**< num bytes still needed to finish read */ + byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */ + + struct read_req_t* next; /**< next read request in the queue */ +}; + + +/** + * @struct vec2b_t + * @brief Unsigned x,y byte vector. + */ +typedef struct vec2b_t { + byte x, y; +} vec2b_t; + + +/** + * @struct vec3b_t + * @brief Unsigned x,y,z byte vector. + */ +typedef struct vec3b_t { + byte x, y, z; +} vec3b_t; + + +/** + * @struct vec3f_t + * @brief Signed x,y,z float struct. + */ +typedef struct vec3f_t { + float x, y, z; +} vec3f_t; + + +/** + * @struct orient_t + * @brief Orientation struct. + * + * Yaw, pitch, and roll range from -180 to 180 degrees. + */ +typedef struct orient_t { + float roll; /**< roll, this may be smoothed if enabled */ + float pitch; /**< pitch, this may be smoothed if enabled */ + float yaw; + + float a_roll; /**< absolute roll, unsmoothed */ + float a_pitch; /**< absolute pitch, unsmoothed */ +} orient_t; + + +/** + * @struct gforce_t + * @brief Gravity force struct. + */ +typedef struct gforce_t { + float x, y, z; +} gforce_t; + + +/** + * @struct accel_t + * @brief Accelerometer struct. For any device with an accelerometer. + */ +typedef struct accel_t { + struct vec3b_t cal_zero; /**< zero calibration */ + struct vec3b_t cal_g; /**< 1g difference around 0cal */ + + float st_roll; /**< last smoothed roll value */ + float st_pitch; /**< last smoothed roll pitch */ + float st_alpha; /**< alpha value for smoothing [0-1] */ +} accel_t; + + +/** + * @struct ir_dot_t + * @brief A single IR source. + */ +typedef struct ir_dot_t { + byte visible; /**< if the IR source is visible */ + + unsigned int x; /**< interpolated X coordinate */ + unsigned int y; /**< interpolated Y coordinate */ + + short rx; /**< raw X coordinate (0-1023) */ + short ry; /**< raw Y coordinate (0-767) */ + + byte order; /**< increasing order by x-axis value */ + + byte size; /**< size of the IR dot (0-15) */ +} ir_dot_t; + + +/** + * @enum aspect_t + * @brief Screen aspect ratio. + */ +typedef enum aspect_t { + WIIUSE_ASPECT_4_3, + WIIUSE_ASPECT_16_9 +} aspect_t; + + +/** + * @struct ir_t + * @brief IR struct. Hold all data related to the IR tracking. + */ +typedef struct ir_t { + struct ir_dot_t dot[4]; /**< IR dots */ + byte num_dots; /**< number of dots at this time */ + + enum aspect_t aspect; /**< aspect ratio of the screen */ + + enum ir_position_t pos; /**< IR sensor bar position */ + + unsigned int vres[2]; /**< IR virtual screen resolution */ + int offset[2]; /**< IR XY correction offset */ + int state; /**< keeps track of the IR state */ + + int ax; /**< absolute X coordinate */ + int ay; /**< absolute Y coordinate */ + + int x; /**< calculated X coordinate */ + int y; /**< calculated Y coordinate */ + + float distance; /**< pixel distance between first 2 dots*/ + float z; /**< calculated distance */ +} ir_t; + + +/** + * @struct joystick_t + * @brief Joystick calibration structure. + * + * The angle \a ang is relative to the positive y-axis into quadrant I + * and ranges from 0 to 360 degrees. So if the joystick is held straight + * upwards then angle is 0 degrees. If it is held to the right it is 90, + * down is 180, and left is 270. + * + * The magnitude \a mag is the distance from the center to where the + * joystick is being held. The magnitude ranges from 0 to 1. + * If the joystick is only slightly tilted from the center the magnitude + * will be low, but if it is closer to the outter edge the value will + * be higher. + */ +typedef struct joystick_t { + struct vec2b_t max; /**< maximum joystick values */ + struct vec2b_t min; /**< minimum joystick values */ + struct vec2b_t center; /**< center joystick values */ + + float ang; /**< angle the joystick is being held */ + float mag; /**< magnitude of the joystick (range 0-1) */ +} joystick_t; + + +/** + * @struct nunchuk_t + * @brief Nunchuk expansion device. + */ +typedef struct nunchuk_t { + struct accel_t accel_calib; /**< nunchuk accelerometer calibration */ + struct joystick_t js; /**< joystick calibration */ + + int* flags; /**< options flag (points to wiimote_t.flags) */ + + byte btns; /**< what buttons have just been pressed */ + byte btns_held; /**< what buttons are being held down */ + byte btns_released; /**< what buttons were just released this */ + + float orient_threshold; /**< threshold for orient to generate an event */ + int accel_threshold; /**< threshold for accel to generate an event */ + + struct vec3b_t accel; /**< current raw acceleration data */ + struct orient_t orient; /**< current orientation on each axis */ + struct gforce_t gforce; /**< current gravity forces on each axis */ +} nunchuk_t; + + +/** + * @struct classic_ctrl_t + * @brief Classic controller expansion device. + */ +typedef struct classic_ctrl_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float r_shoulder; /**< right shoulder button (range 0-1) */ + float l_shoulder; /**< left shoulder button (range 0-1) */ + + struct joystick_t ljs; /**< left joystick calibration */ + struct joystick_t rjs; /**< right joystick calibration */ +} classic_ctrl_t; + + +/** + * @struct guitar_hero_3_t + * @brief Guitar Hero 3 expansion device. + */ +typedef struct guitar_hero_3_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float whammy_bar; /**< whammy bar (range 0-1) */ + + struct joystick_t js; /**< joystick calibration */ +} guitar_hero_3_t; + + +/** + * @struct expansion_t + * @brief Generic expansion device plugged into wiimote. + */ +typedef struct expansion_t { + int type; /**< type of expansion attached */ + + union { + struct nunchuk_t nunchuk; + struct classic_ctrl_t classic; + struct guitar_hero_3_t gh3; + }; +} expansion_t; + + +/** + * @enum win32_bt_stack_t + * @brief Available bluetooth stacks for Windows. + */ +typedef enum win_bt_stack_t { + WIIUSE_STACK_UNKNOWN, + WIIUSE_STACK_MS, + WIIUSE_STACK_BLUESOLEIL +} win_bt_stack_t; + + +/** + * @struct wiimote_state_t + * @brief Significant data from the previous event. + */ +typedef struct wiimote_state_t { + /* expansion_t */ + float exp_ljs_ang; + float exp_rjs_ang; + float exp_ljs_mag; + float exp_rjs_mag; + unsigned short exp_btns; + struct orient_t exp_orient; + struct vec3b_t exp_accel; + float exp_r_shoulder; + float exp_l_shoulder; + + /* ir_t */ + int ir_ax; + int ir_ay; + float ir_distance; + + struct orient_t orient; + unsigned short btns; + + struct vec3b_t accel; +} wiimote_state_t; + + +/** + * @enum WIIUSE_EVENT_TYPE + * @brief Events that wiiuse can generate from a poll. + */ +typedef enum WIIUSE_EVENT_TYPE { + WIIUSE_NONE = 0, + WIIUSE_EVENT, + WIIUSE_STATUS, + WIIUSE_CONNECT, + WIIUSE_DISCONNECT, + WIIUSE_UNEXPECTED_DISCONNECT, + WIIUSE_READ_DATA, + WIIUSE_NUNCHUK_INSERTED, + WIIUSE_NUNCHUK_REMOVED, + WIIUSE_CLASSIC_CTRL_INSERTED, + WIIUSE_CLASSIC_CTRL_REMOVED, + WIIUSE_GUITAR_HERO_3_CTRL_INSERTED, + WIIUSE_GUITAR_HERO_3_CTRL_REMOVED +} WIIUSE_EVENT_TYPE; + +/** + * @struct wiimote_t + * @brief Wiimote structure. + */ +typedef struct wiimote_t { + WCONST int unid; /**< user specified id */ + + #ifndef WIN32 + WCONST bdaddr_t bdaddr; /**< bt address */ + WCONST char bdaddr_str[18]; /**< readable bt address */ + WCONST int out_sock; /**< output socket */ + WCONST int in_sock; /**< input socket */ + #else + WCONST HANDLE dev_handle; /**< HID handle */ + WCONST OVERLAPPED hid_overlap; /**< overlap handle */ + WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */ + WCONST int timeout; /**< read timeout */ + WCONST byte normal_timeout; /**< normal timeout */ + WCONST byte exp_timeout; /**< timeout for expansion handshake */ + #endif + + WCONST int state; /**< various state flags */ + WCONST byte leds; /**< currently lit leds */ + WCONST float battery_level; /**< battery level */ + + WCONST int flags; /**< options flag */ + + WCONST byte handshake_state; /**< the state of the connection handshake */ + + WCONST struct read_req_t* read_req; /**< list of data read requests */ + WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */ + WCONST struct expansion_t exp; /**< wiimote expansion device */ + + WCONST struct vec3b_t accel; /**< current raw acceleration data */ + WCONST struct orient_t orient; /**< current orientation on each axis */ + WCONST struct gforce_t gforce; /**< current gravity forces on each axis */ + + WCONST struct ir_t ir; /**< IR data */ + + WCONST unsigned short btns; /**< what buttons have just been pressed */ + WCONST unsigned short btns_held; /**< what buttons are being held down */ + WCONST unsigned short btns_released; /**< what buttons were just released this */ + + WCONST float orient_threshold; /**< threshold for orient to generate an event */ + WCONST int accel_threshold; /**< threshold for accel to generate an event */ + + WCONST struct wiimote_state_t lstate; /**< last saved state */ + + WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */ + WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */ +} wiimote; + + +/***************************************** + * + * Include API specific stuff + * + *****************************************/ + +#ifdef _WIN32 + #define WIIUSE_EXPORT_DECL __declspec(dllexport) + #define WIIUSE_IMPORT_DECL __declspec(dllimport) +#else + #define WIIUSE_EXPORT_DECL + #define WIIUSE_IMPORT_DECL +#endif + +#ifdef WIIUSE_COMPILE_LIB + #define WIIUSE_EXPORT WIIUSE_EXPORT_DECL +#else + #define WIIUSE_EXPORT WIIUSE_IMPORT_DECL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* wiiuse.c */ +WIIUSE_EXPORT extern const char* wiiuse_version(); + +WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds); +WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len); +WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len); +WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm); +WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid); +WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable); +WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha); +WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type); +WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout); +WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold); + +/* connect.c */ +WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout); +WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm); + +/* events.c */ +WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes); + +/* ir.c */ +WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y); +WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos); +WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect); +WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); + +/* nunchuk.c */ +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold); + + +#ifdef __cplusplus +} +#endif + + +#endif /* WIIUSE_H_INCLUDED */ +