diff options
| author | Shawn Hoffman <godisgovernment@gmail.com> | 2010-11-13 19:15:43 +0000 |
|---|---|---|
| committer | Shawn Hoffman <godisgovernment@gmail.com> | 2010-11-13 19:15:43 +0000 |
| commit | 7ad7acd248e73dfa60f28767dc6373c5df571ccd (patch) | |
| tree | 4970bb11da921d56457ffaa71713f26f90d525d9 /Source/Core | |
| parent | 8eb1fe883163423528499b7c1e9af858385eeffc (diff) | |
move wiiuse to Source/Core and add to the main dolphin solution
make wiiuse link dynamically with hid.dll, removing the need for WDK
compile wiiuse as c++
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6394 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Source/Core/Core/Core.vcproj | 30 | ||||
| -rw-r--r-- | Source/Core/wiiuse/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/SConscript | 21 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/definitions.h | 53 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/io_dummy.cpp | 27 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/io_nix.cpp | 328 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/io_osx.m | 341 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/io_win.cpp | 454 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/ir.cpp | 135 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/wiiuse.cpp | 406 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/wiiuse.h | 221 | ||||
| -rw-r--r-- | Source/Core/wiiuse/Src/wiiuse_internal.h | 163 | ||||
| -rw-r--r-- | Source/Core/wiiuse/wiiuse.sln | 26 | ||||
| -rw-r--r-- | Source/Core/wiiuse/wiiuse.vcproj | 404 |
15 files changed, 2608 insertions, 18 deletions
diff --git a/Source/Core/CMakeLists.txt b/Source/Core/CMakeLists.txt index ff9b5c9ae9..beef930d70 100644 --- a/Source/Core/CMakeLists.txt +++ b/Source/Core/CMakeLists.txt @@ -13,3 +13,4 @@ add_subdirectory(DolphinWX) add_subdirectory(DSPCore) add_subdirectory(InputCommon) add_subdirectory(VideoCommon) +add_subdirectory(wiiuse) diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index 49d525b76a..779540b73a 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -45,7 +45,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -69,9 +69,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiused.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" @@ -116,7 +115,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -140,9 +139,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiused.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" @@ -191,7 +189,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" EnableFiberSafeOptimizations="false" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0" StringPooling="true" RuntimeLibrary="0" @@ -215,9 +213,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiuse.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" @@ -269,7 +266,7 @@ OmitFramePointers="true" EnableFiberSafeOptimizations="false" WholeProgramOptimization="false" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0" StringPooling="true" RuntimeLibrary="0" @@ -293,9 +290,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiuse.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\Lua\$(OutDir)\Lua.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" @@ -344,7 +340,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" EnableFiberSafeOptimizations="false" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0" RuntimeLibrary="0" BufferSecurityCheck="true" @@ -367,9 +363,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiuse.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" @@ -419,7 +414,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" EnableFiberSafeOptimizations="false" - AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include;..\..\..\Externals\WiiUse\Src" + AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\wiiuse\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include" PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0" RuntimeLibrary="0" BufferSecurityCheck="false" @@ -441,9 +436,8 @@ /> <Tool Name="VCLibrarianTool" - AdditionalDependencies="wiiuse.lib" OutputFile="$(OutDir)/Core.lib" - AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib";"..\..\..\Externals\WiiUse\$(PlatformName)"" + AdditionalLibraryDirectories=""..\..\..\Externals\LZO\$(OutDir)\lzo.lib"" /> <Tool Name="VCALinkTool" diff --git a/Source/Core/wiiuse/CMakeLists.txt b/Source/Core/wiiuse/CMakeLists.txt new file mode 100644 index 0000000000..adfefe6ae0 --- /dev/null +++ b/Source/Core/wiiuse/CMakeLists.txt @@ -0,0 +1,16 @@ +set(SRCS Src/ir.cpp + Src/wiiuse.cpp) + +if(APPLE) + set(SRCS ${SRCS} Src/io_osx.m) +elseif(UNIX AND BLUEZ_FOUND) + set(SRCS ${SRCS} Src/io_nix.cpp) + set(LIBS ${LIBS} bluetooth) +elseif(WIN32) + set(SRCS ${SRCS} Src/io_win.cpp) +else() + set(SRCS ${SRCS} Src/io_dummy.cpp) +endif() + +add_library(wiiuse STATIC ${SRCS}) +target_link_libraries(wiiuse ${LIBS}) diff --git a/Source/Core/wiiuse/Src/SConscript b/Source/Core/wiiuse/Src/SConscript new file mode 100644 index 0000000000..263880b412 --- /dev/null +++ b/Source/Core/wiiuse/Src/SConscript @@ -0,0 +1,21 @@ +# -*- python -*- + +Import('env') +import sys + +files = [ + "ir.cpp", + "wiiuse.cpp", + ] + +if sys.platform == 'darwin': + files += [ "io_osx.m" ] +elif sys.platform == 'linux2' and env['HAVE_BLUEZ']: + files += [ "io_nix.cpp" ] +elif sys.platform == 'win32': + files += [ "io_win.cpp" ] +else: + files += [ "io_dummy.cpp" ] + +env.StaticLibrary(env['local_libs'] + "wiiuse", files) +env['CPPPATH'] += ['#Source/Core/wiiuse/Src'] diff --git a/Source/Core/wiiuse/Src/definitions.h b/Source/Core/wiiuse/Src/definitions.h new file mode 100644 index 0000000000..5ddb06fd81 --- /dev/null +++ b/Source/Core/wiiuse/Src/definitions.h @@ -0,0 +1,53 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief General definitions. + */ + +#ifndef DEFINITIONS_H_INCLUDED +#define DEFINITIONS_H_INCLUDED + +#include <Common.h> + +#ifndef _WIN32 +#include <arpa/inet.h> /* htons() */ +#else +/* disable warnings I don't care about */ +#pragma warning(disable:4244) /* possible loss of data conversion */ +#pragma warning(disable:4273) /* inconsistent dll linkage */ +#pragma warning(disable:4217) + +#endif // _WIN32 + +/* Convert to big endian */ +#define BIG_ENDIAN_LONG(i) (htonl(i)) +#define BIG_ENDIAN_SHORT(i) (htons(i)) + +#endif // DEFINITIONS_H_INCLUDED diff --git a/Source/Core/wiiuse/Src/io_dummy.cpp b/Source/Core/wiiuse/Src/io_dummy.cpp new file mode 100644 index 0000000000..f865a42fe4 --- /dev/null +++ b/Source/Core/wiiuse/Src/io_dummy.cpp @@ -0,0 +1,27 @@ +#include "definitions.h" +#include "wiiuse_internal.h" + +int wiiuse_find(struct wiimote_t **wm, int max_wiimotes, int timeout) +{ + return 0; +} + +int wiiuse_connect(struct wiimote_t **wm, int wiimotes) +{ + return 0; +} + +void wiiuse_disconnect(struct wiimote_t *wm) +{ + return; +} + +int wiiuse_io_read(struct wiimote_t *wm) +{ + return 0; +} + +int wiiuse_io_write(struct wiimote_t *wm, byte *buf, int len) +{ + return 0; +} diff --git a/Source/Core/wiiuse/Src/io_nix.cpp b/Source/Core/wiiuse/Src/io_nix.cpp new file mode 100644 index 0000000000..6e7fe2bd56 --- /dev/null +++ b/Source/Core/wiiuse/Src/io_nix.cpp @@ -0,0 +1,328 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <sys/time.h> +#include <errno.h> + +#include <sys/types.h> +#include <stdlib.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> +#include <bluetooth/l2cap.h> + +#include "definitions.h" +#include "wiiuse_internal.h" + +static int wiiuse_connect_single(struct wiimote_t* wm, char* address); + +// Find a wiimote or wiimotes. +// Does not replace already found wiimotes even if they are disconnected. +// wm An array of wiimote_t structures. +// max_wiimotes The number of wiimote structures in wm. +// timeout The number of seconds before the search times out. +// Returns the total number of found wiimotes. +// This function will only look for wiimote devices. +// When a device is found the address in the structures will be set. +// You can then call wiimote_connect() to connect to the found devices. +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) +{ + int device_id; + int device_sock; + int found_devices; + int found_wiimotes = 0; + int i; + + // Count the number of already found wiimotes + for (i = 0; i < max_wiimotes; ++i) + { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + found_wiimotes++; + } + + // get the id of the first bluetooth device. + device_id = hci_get_route(NULL); + if (device_id < 0) + { + perror("hci_get_route"); + return 0; + } + + // create a socket to the device + device_sock = hci_open_dev(device_id); + if (device_sock < 0) + { + perror("hci_open_dev"); + return 0; + } + + int try_num = 0; + while ((try_num < timeout) && (found_wiimotes < max_wiimotes)) + { + inquiry_info scan_info_arr[128]; + inquiry_info* scan_info = scan_info_arr; + memset(&scan_info_arr, 0, sizeof(scan_info_arr)); + + // scan for bluetooth devices for ~one second + found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); + if (found_devices < 0) + { + perror("hci_inquiry"); + return 0; + } + + NOTICE_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); + + // display discovered devices + for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) + { + if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && + (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && + (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + { + int new_wiimote = 1; + int j; + // Determine if this wiimote has already been found. + for (j = 0; j < found_wiimotes && new_wiimote; ++j) + { + if (WIIMOTE_IS_SET(wm[j], WIIMOTE_STATE_DEV_FOUND) && + bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) + new_wiimote = 0; + } + + if (new_wiimote) + { + // found a new device + ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); + + NOTICE_LOG(WIIMOTE, "Found wiimote (%s) [id %i].", + wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); + + wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; + WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); + ++found_wiimotes; + } + } + } + try_num++; + } + + close(device_sock); + return found_wiimotes; +} + +// Connect to a wiimote or wiimotes once an address is known. +// wm An array of wiimote_t structures. +// wiimotes The number of wiimote structures in wm. +// Return the number of wiimotes that successfully connected. +// Connect to a number of wiimotes when the address is already set +// in the wiimote_t structures. These addresses are normally set +// by the wiiuse_find() function, but can also be set manually. +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) +{ + int connected = 0; + int i = 0; + + for (; i < wiimotes; ++i) + { + if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + // if the device address is not set, skip it + continue; + + if (wiiuse_connect_single(wm[i], NULL)) + ++connected; + } + + return connected; +} + +// Connect to a wiimote with a known address. +// wm Pointer to a wiimote_t structure. +// address The address of the device to connect to. +// If NULL, use the address in the struct set by wiiuse_find(). +// Return 1 on success, 0 on failure +static int wiiuse_connect_single(struct wiimote_t* wm, char* address) +{ + struct sockaddr_l2 addr; + + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return 0; + + addr.l2_family = AF_BLUETOOTH; + bdaddr_t *bdaddr = &wm->bdaddr; + if (address) + // use provided address + str2ba(address, &addr.l2_bdaddr); + else + { + if (bacmp(bdaddr, BDADDR_ANY) == 0) + return 0; + // use address of device discovered + addr.l2_bdaddr = *bdaddr; + + } + + // OUTPUT CHANNEL + wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->out_sock == -1) + return 0; + + addr.l2_cid = 0; + addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); + + // connect to wiimote + if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { + perror("connect() output sock"); + return 0; + } + + // INPUT CHANNEL + wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->in_sock == -1) + { + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + addr.l2_psm = htobs(WM_INPUT_CHANNEL); + + // connect to wiimote + if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { + perror("connect() interrupt sock"); + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + NOTICE_LOG(WIIMOTE, "Connected to wiimote [id %i].", wm->unid); + // do the handshake + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + + wiiuse_set_report_type(wm); + + return 1; +} + +// Disconnect a wiimote. +// wm Pointer to a wiimote_t structure. +// Note that this will not free the wiimote structure. +void wiiuse_disconnect(struct wiimote_t* wm) +{ + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + close(wm->out_sock); + close(wm->in_sock); + + wm->out_sock = -1; + wm->in_sock = -1; + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + +int wiiuse_io_read(struct wiimote_t* wm) +{ + struct timeval tv; + fd_set fds; + int r; + if (!wm) + return 0; + + // block select() for 1/2000th of a second + tv.tv_sec = 0; + tv.tv_usec = wm->timeout * 1000; // timeout is in Milliseconds tv_usec is in Microseconds! + + FD_ZERO(&fds); + // only poll it if it is connected + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) + { + FD_SET(wm->in_sock, &fds); + //highest_fd = wm[i]->in_sock; + } + else + // nothing to poll + return 0; + + if (select(wm->in_sock + 1, &fds, NULL, NULL, &tv) == -1) + { + ERROR_LOG(WIIMOTE, "Unable to select() the wiimote interrupt socket(s)."); + perror("Error Details"); + return 0; + } + + // if this wiimote is not connected, skip it + if (!WIIMOTE_IS_CONNECTED(wm)) + return 0; + + if (FD_ISSET(wm->in_sock, &fds)) + { + //memset(wm->event_buf, 0, sizeof(wm->event_buf)); + // read the pending message into the buffer + r = read(wm->in_sock, wm->event_buf, sizeof(wm->event_buf)); + if (r == -1) + { + // error reading data + ERROR_LOG(WIIMOTE, "Receiving wiimote data (id %i).", wm->unid); + perror("Error Details"); + + if (errno == ENOTCONN) + { + // this can happen if the bluetooth dongle is disconnected + ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm->unid); + wiiuse_disconnect(wm); + wm->event = WIIUSE_UNEXPECTED_DISCONNECT; + } + + return 0; + } + if (!r) + { + // remote disconnect + wiiuse_disconnected(wm); + return 0; + } + wm->event_buf[0] = 0xa2; // Make sure it's 0xa2, just in case + return 1; + } + return 0; +} + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) +{ + if(buf[0] == 0xa2) + buf[0] = 0x52; // May not be needed. Will be changing/correcting in the next few revisions + return write(wm->out_sock, buf, len); +} diff --git a/Source/Core/wiiuse/Src/io_osx.m b/Source/Core/wiiuse/Src/io_osx.m new file mode 100644 index 0000000000..3ad835b7ea --- /dev/null +++ b/Source/Core/wiiuse/Src/io_osx.m @@ -0,0 +1,341 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for OS X. + */ + +#import <CoreServices/CoreServices.h> +extern OSErr UpdateSystemActivity(UInt8 activity); +#define BLUETOOTH_VERSION_USE_CURRENT +#import <IOBluetooth/objc/IOBluetoothDevice.h> +#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h> +#import <IOBluetooth/objc/IOBluetoothHostController.h> +#import <IOBluetooth/objc/IOBluetoothL2CAPChannel.h> + +#include "definitions.h" +#include "wiiuse_internal.h" + +static int wiiuse_connect_single(struct wiimote_t *wm, char *address); + +IOBluetoothDevice *btd; +IOBluetoothL2CAPChannel *ichan; +IOBluetoothL2CAPChannel *cchan; + +#define QUEUE_SIZE 64 +volatile struct buffer { + char data[MAX_PAYLOAD]; + int len; +} queue[QUEUE_SIZE]; +volatile int reader, writer, outstanding, watermark; + +@interface SearchBT: NSObject { +@public + unsigned int maxDevices; +} +@end + +@implementation SearchBT +- (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender + error: (IOReturn) error + aborted: (BOOL) aborted +{ + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +- (void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry *) sender + device: (IOBluetoothDevice *) device +{ + NOTICE_LOG(WIIMOTE, "Discovered bluetooth device at %s: %s", + [[device getAddressString] UTF8String], + [[device getName] UTF8String]); + + if ([[sender foundDevices] count] == maxDevices) + [sender stop]; +} +@end + +@interface ConnectBT: NSObject {} +@end + +@implementation ConnectBT +- (void) l2capChannelData: (IOBluetoothL2CAPChannel *) l2capChannel + data: (byte *) data + length: (NSUInteger) length +{ + // IOBluetoothDevice *device = [l2capChannel getDevice]; + + if (length > MAX_PAYLOAD) { + WARN_LOG(WIIMOTE, "Dropping wiimote packet - too large"); + return; + } + + if (queue[writer].len != 0) { + WARN_LOG(WIIMOTE, "Dropping wiimote packet - queue full"); + return; + } + + memcpy(queue[writer].data, data, length); + queue[writer].len = length; + + writer++; + outstanding++; + if (writer == QUEUE_SIZE) + writer = 0; + + if (outstanding > watermark) { + watermark = outstanding; + WARN_LOG(WIIMOTE, "New wiimote queue watermark %d", watermark); + } + + CFRunLoopStop(CFRunLoopGetCurrent()); + + UpdateSystemActivity(1); +} + +- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel +{ + // IOBluetoothDevice *device = [l2capChannel getDevice]; + + WARN_LOG(WIIMOTE, "L2CAP channel was closed"); + + if (l2capChannel == cchan) + cchan = nil; + + if (l2capChannel == ichan) + ichan = nil; +} +@end + +/** + * @brief Find a wiimote or wiimotes. + * + * @param wm An array of wiimote_t structures. + * @param max_wiimotes The number of wiimote structures in \a wm. + * @param timeout The number of seconds before timing out. + * + * @return The number of wiimotes found. + * + * @see wiiuse_connect() + * + * This function will only look for wiimote devices. + * When a device is found the address in the structures will be set. + * You can then call wiiuse_connect() to connect to the found + * devices. + */ +int wiiuse_find(struct wiimote_t **wm, int max_wiimotes, int timeout) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + IOBluetoothHostController *bth; + IOBluetoothDeviceInquiry *bti; + SearchBT *sbt; + NSEnumerator *en; + int i, found_devices = 0; + + bth = [[IOBluetoothHostController alloc] init]; + if ([bth addressAsString] == nil) + { + WARN_LOG(WIIMOTE, "No bluetooth host controller"); + [bth release]; + return 0; + } + + sbt = [[SearchBT alloc] init]; + sbt->maxDevices = max_wiimotes; +/*XXX*/ sbt->maxDevices = 1; + bti = [[IOBluetoothDeviceInquiry alloc] init]; + [bti setDelegate: sbt]; + [bti setInquiryLength: timeout]; + [bti setSearchCriteria: kBluetoothServiceClassMajorAny + majorDeviceClass: kBluetoothDeviceClassMajorPeripheral + minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick + ]; + + IOReturn ret = [bti start]; + if (ret == kIOReturnSuccess) + [bti retain]; + else + ERROR_LOG(WIIMOTE, "Unable to do bluetooth discovery"); + + CFRunLoopRun(); + + [bti stop]; + found_devices = [[bti foundDevices] count]; + + NOTICE_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); + + en = [[bti foundDevices] objectEnumerator]; + for (i = 0; i < found_devices; i++) { + btd = [en nextObject]; + WIIMOTE_ENABLE_STATE(wm[i], WIIMOTE_STATE_DEV_FOUND); + } + + [bth release]; + [bti release]; + [sbt release]; + [pool release]; + + return found_devices; +} + +/** + * @brief Connect to a wiimote or wiimotes once an address is known. + * + * @param wm An array of wiimote_t structures. + * @param wiimotes The number of wiimote structures in \a wm. + * + * @return The number of wiimotes that successfully connected. + * + * @see wiiuse_find() + * @see wiiuse_connect_single() + * @see wiiuse_disconnect() + * + * Connect to a number of wiimotes when the address is already set + * in the wiimote_t structures. These addresses are normally set + * by the wiiuse_find() function, but can also be set manually. + */ +int wiiuse_connect(struct wiimote_t **wm, int wiimotes) +{ + int i, connected = 0; + + for (i = 0; i < wiimotes; ++i) + { + if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + continue; + + if (wiiuse_connect_single(wm[i], NULL)) + connected++; + } + + return connected; +} + +/** + * @brief Connect to a wiimote with a known address. + * + * @param wm Pointer to a wiimote_t structure. + * @param address The address of the device to connect to. If NULL, + * use the address in the struct set by wiiuse_find(). + * + * @return 1 on success, 0 on failure + */ +static int wiiuse_connect_single(struct wiimote_t *wm, char *address) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + ConnectBT *cbt = [[ConnectBT alloc] init]; + + if (wm == NULL || WIIMOTE_IS_CONNECTED(wm)) + return 0; + + [btd openL2CAPChannelSync: &cchan + withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt]; + [btd openL2CAPChannelSync: &ichan + withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt]; + if (ichan == NULL || cchan == NULL) { + ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels"); + wiiuse_disconnect(wm); + } + + NOTICE_LOG(WIIMOTE, "Connected to wiimote [id %i].", wm->unid); + + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + wiiuse_set_report_type(wm); + + [cbt release]; + [pool release]; + + return 1; +} + +/** + * @brief Disconnect a wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_connect() + * + * Note that this will not free the wiimote structure. + */ +void wiiuse_disconnect(struct wiimote_t *wm) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if (wm == NULL) + return; + + NOTICE_LOG(WIIMOTE, "Disconnecting wiimote [id %i]", wm->unid); + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); + + [cchan closeChannel]; + [ichan closeChannel]; + [btd closeConnection]; + [pool release]; +} + +int wiiuse_io_read(struct wiimote_t *wm) +{ + int bytes; + + if (!WIIMOTE_IS_CONNECTED(wm)) + return 0; + + if (outstanding == 0) + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, true); + + if (queue[reader].len == 0) + return 0; + + bytes = queue[reader].len; + memcpy(wm->event_buf, queue[reader].data, bytes); + queue[reader].len = 0; + + reader++; + outstanding--; + if (reader == QUEUE_SIZE) + reader = 0; + + if (wm->event_buf[0] == '\0') + bytes = 0; + + return bytes; +} + +int wiiuse_io_write(struct wiimote_t *wm, byte *buf, int len) +{ + IOReturn ret; + + ret = [cchan writeAsync: buf length: len refcon: nil]; + + if (ret == kIOReturnSuccess) + return len; + else + return 0; +} diff --git a/Source/Core/wiiuse/Src/io_win.cpp b/Source/Core/wiiuse/Src/io_win.cpp new file mode 100644 index 0000000000..4ec7a05b0f --- /dev/null +++ b/Source/Core/wiiuse/Src/io_win.cpp @@ -0,0 +1,454 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for Windows. + */ + +#ifdef _WIN32 + +#include <stdio.h> +#include <stdlib.h> + +#include <windows.h> +#include <dbt.h> +#include <setupapi.h> + +#include "definitions.h" +#include "wiiuse_internal.h" + +#include <Common.h> + +typedef struct _HIDD_ATTRIBUTES { + ULONG Size; + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; +} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + +typedef VOID (__stdcall *PHidD_GetHidGuid)(LPGUID); +typedef BOOLEAN (__stdcall *PHidD_GetAttributes)(HANDLE, PHIDD_ATTRIBUTES); +typedef BOOLEAN (__stdcall *PHidD_SetOutputReport)(HANDLE, PVOID, ULONG); + +PHidD_GetHidGuid HidD_GetHidGuid = NULL; +PHidD_GetAttributes HidD_GetAttributes = NULL; +PHidD_SetOutputReport HidD_SetOutputReport = NULL; + +HINSTANCE hid_lib = NULL; + +static int initialized = 0; + +inline void init_lib() +{ + if (!initialized) + { + hid_lib = LoadLibrary(L"hid.dll"); + if (!hid_lib) + { + PanicAlert("Failed to load hid.dll"); + exit(EXIT_FAILURE); + } + + HidD_GetHidGuid = (PHidD_GetHidGuid)GetProcAddress(hid_lib, "HidD_GetHidGuid"); + HidD_GetAttributes = (PHidD_GetAttributes)GetProcAddress(hid_lib, "HidD_GetAttributes"); + HidD_SetOutputReport = (PHidD_SetOutputReport)GetProcAddress(hid_lib, "HidD_SetOutputReport"); + if (!HidD_GetHidGuid || !HidD_GetAttributes || !HidD_SetOutputReport) + { + PanicAlert("Failed to load hid.dll"); + exit(EXIT_FAILURE); + } + + initialized = true; + } +} + +int wiiuse_remove(struct wiimote_t** wm, int wiimotes, int max_wiimotes); + +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int wiimotes) { + GUID device_id; + HANDLE dev; + HDEVINFO device_info; + int i, x, found, index, udisc = 0; + DWORD len; + SP_DEVICE_INTERFACE_DATA device_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; + HIDD_ATTRIBUTES attr; + + init_lib(); + + // todo: handle/remove (unexpected and forced) disconnected wiimotes here + + // removal of unneeded wiimotes and exiting when we got enough wiimotes connected + if (wiiuse_remove(wm, wiimotes, max_wiimotes)) + return max_wiimotes; + + device_data.cbSize = sizeof(device_data); + + // get the device id + HidD_GetHidGuid(&device_id); + + // get all hid devices connected + device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); + + for (index = 0; wiimotes < max_wiimotes; ++index) { + + if (detail_data) { + free(detail_data); + detail_data = NULL; + } + found = 0; + + // query the next hid device info + if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) + break; + + // get the size of the data block required + i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); + detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); + detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + // query the data for this device + if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) + continue; + + // Wiimote already added + for(x = 0; x < wiimotes; x++) + { + if(memcmp(wm[x]->devicepath,detail_data->DevicePath,197) == 0) { + found = 1; + break; + } + } + if (found) + continue; + + // open new device + dev = CreateFile(detail_data->DevicePath, + (GENERIC_READ | GENERIC_WRITE), + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (dev == INVALID_HANDLE_VALUE) + continue; + + + + // get device attributes + attr.Size = sizeof(attr); + i = HidD_GetAttributes(dev, &attr); + + if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) { + + + //this is a wiimote + wm[wiimotes]->dev_handle = dev; + + wm[wiimotes]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, L""); + wm[wiimotes]->hid_overlap.Offset = 0; + wm[wiimotes]->hid_overlap.OffsetHigh = 0; + + WIIMOTE_ENABLE_STATE(wm[wiimotes], WIIMOTE_STATE_DEV_FOUND); + WIIMOTE_ENABLE_STATE(wm[wiimotes], WIIMOTE_STATE_CONNECTED); + WIIMOTE_ENABLE_STATE(wm[wiimotes], WIIUSE_CONTINUOUS); + // try to set the output report to see if the device is actually connected + + if (!wiiuse_set_report_type(wm[wiimotes])) { + WIIMOTE_DISABLE_STATE(wm[wiimotes], WIIMOTE_STATE_CONNECTED); + if (wm[wiimotes]->event == WIIUSE_UNEXPECTED_DISCONNECT) + { + wiiuse_disconnect(wm[wiimotes]); + memset(wm[wiimotes],0,sizeof(wm[wiimotes])); + } + continue; + } + + memcpy(wm[wiimotes]->devicepath,detail_data->DevicePath,197); + NOTICE_LOG(WIIMOTE, "Connected to wiimote [id %i].", wm[wiimotes]->unid); + ++wiimotes; + + } else { + // not a wiimote + CloseHandle(dev); + } + } + + if (detail_data) + free(detail_data); + + SetupDiDestroyDeviceInfoList(device_info); + + return wiimotes; +} + +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) +{ + int i, connected = 0; + + init_lib(); + + for (i = 0; i < wiimotes; ++i) + { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) + ++connected; + } + + return connected; +} + +void wiiuse_disconnect(struct wiimote_t* wm) +{ + init_lib(); + + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return; + + CloseHandle(wm->dev_handle); + wm->dev_handle = 0; + + ResetEvent(&wm->hid_overlap); + + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + +int wiiuse_io_read(struct wiimote_t* wm) +{ + DWORD b, r; + + init_lib(); + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) { + /* partial read */ + b = GetLastError(); + + if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { + /* remote disconnect */ + wiiuse_disconnected(wm); + wm->event = WIIUSE_UNEXPECTED_DISCONNECT; + return 0; + } + + r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout); + if (r == WAIT_TIMEOUT) { + /* timeout - cancel and continue */ + + if (*wm->event_buf) + WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).", wm->timeout); + + CancelIo(wm->dev_handle); + ResetEvent(wm->hid_overlap.hEvent); + return 0; + } else if (r == WAIT_FAILED) { + WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", wm->unid); + return 0; + } + + if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0)) + return 0; + } + + // This needs to be done even if ReadFile fails, essential during init + // Move the data over one, so we can add back in data report indicator byte (here, 0xa1) + memmove(wm->event_buf + 1, wm->event_buf, sizeof(wm->event_buf) - 1); + wm->event_buf[0] = 0xa1; + + ResetEvent(wm->hid_overlap.hEvent); + return 1; +} + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) +{ + DWORD bytes, dw; + int i; + + init_lib(); + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + switch (wm->stack) { + case WIIUSE_STACK_UNKNOWN: + { + /* try to auto-detect the stack type */ + if (i = WriteFile(wm->dev_handle, buf + 1, 22, &bytes, &wm->hid_overlap)) { + /* bluesoleil will always return 1 here, even if it's not connected */ + wm->stack = WIIUSE_STACK_BLUESOLEIL; + return i; + } + + if (i = HidD_SetOutputReport(wm->dev_handle, buf + 1, len - 1)) { + wm->stack = WIIUSE_STACK_MS; + return i; + } + + /*-------------------------------------------------------------- + dw = GetLastError(); //checking for 121 = timeout on semaphore/device off/disconnected to avoid trouble with other stacks toshiba/widcomm + //995 = The I/O operation has been aborted because of either a thread exit or an application request. + + if ( (dw == 121) || (dw == 995) ) { + NOTICE_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_UNKNOWN]: WIIUSE_UNEXPECTED_DISCONNECT"); + wiiuse_disconnected(wm); + wm->event = WIIUSE_UNEXPECTED_DISCONNECT; + } + else ERROR_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_UNKNOWN]: WIIUSE_UNEXPECTED_DISCONNECT ERROR: %08x", dw); + --------------------------------------------------------------*/ + + //If the part below causes trouble on WIDCOMM/TOSHIBA stack uncomment the lines above, and comment out the 3 lines below instead. + + NOTICE_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_UNKNOWN]: WIIUSE_UNEXPECTED_DISCONNECT - time out"); + wiiuse_disconnected(wm); + wm->event = WIIUSE_UNEXPECTED_DISCONNECT; + + //ERROR_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_UNKNOWN]: Unable to determine bluetooth stack type || Wiimote timed out."); + return 0; + } + + case WIIUSE_STACK_MS: + i = HidD_SetOutputReport(wm->dev_handle, buf + 1, len - 1); + dw = GetLastError(); + + if (dw == 121) { // semaphore timeout + NOTICE_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_MS]: WIIUSE_UNEXPECTED_DISCONNECT"); + wiiuse_disconnected(wm); + wm->event = WIIUSE_UNEXPECTED_DISCONNECT; + return 0; + }/* else if (dw) + ERROR_LOG(WIIMOTE, "wiiuse_io_write[WIIUSE_STACK_MS]: WIIUSE_UNEXPECTED_DISCONNECT ERROR: %08x", dw); + */ + // it is not important to catch all errors here at this place, rest will be covered by io_reads. + return i; + + case WIIUSE_STACK_BLUESOLEIL: + return WriteFile(wm->dev_handle, buf + 1, 22, &bytes, &wm->hid_overlap); + } + + return 0; +} + +//Checks if the corresponding device to a system notification is a wiimote +//I placed the code here to avoid ddk/wdk dependencies @wiimote plugin +int wiiuse_check_system_notification(unsigned int nMsg, WPARAM wParam, LPARAM lParam) +{ + PDEV_BROADCAST_HDR pDevice = (PDEV_BROADCAST_HDR)lParam; + + init_lib(); + + switch(pDevice->dbch_devicetype) + { + case DBT_DEVTYP_DEVICEINTERFACE: + { + PDEV_BROADCAST_DEVICEINTERFACE pDeviceInfo = (PDEV_BROADCAST_DEVICEINTERFACE)pDevice; + HIDD_ATTRIBUTES attr; + char stringbuf[255]; + + HANDLE dev = CreateFile(pDeviceInfo->dbcc_name, + 0,(FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + + if (dev != INVALID_HANDLE_VALUE) + { + attr.Size = sizeof(attr); + HidD_GetAttributes(dev, &attr); + + //Checking PID&VID + if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) { + CloseHandle(dev); + return 1; + } + + CloseHandle(dev); + } + else + { + // different method to acquire the "wiimote vid/pid" for a + // comparison when the device is already unavailable @CreateFile() + wcstombs(stringbuf, pDeviceInfo->dbcc_name, 255); + //ms bt stack + bluesoleil vid/pid dbccname format + if ( (strstr(stringbuf, "VID&0002057e_PID&0306") != NULL) || + (strstr(stringbuf, "VID_057e&PID_0306") != NULL) ) + { + return 1; + } + } + + return 0; + } + + default: + return 0; + + } + return 0; +} + +//register a handle for device notifications +int wiiuse_register_system_notification(HWND hwnd) +{ + DEV_BROADCAST_DEVICEINTERFACE Filter; + ZeroMemory(&Filter, sizeof(Filter)); + + init_lib(); + + //GUID wiimoteguid; + //CLSIDFromString(_T("745a17a0-74d3-11d0-b6fe-00a0c90f57da"),&wiimoteguid); + Filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + Filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + //Filter.dbcc_classguid = wiimoteguid; + + return (int)RegisterDeviceNotification(hwnd, &Filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); +} + +int wiiuse_remove(struct wiimote_t** wm, int wiimotes, int max_wiimotes) +{ + int i = 0; + NOTICE_LOG(WIIMOTE, "Remove Wiimotes, WM: %i MAX_WM: %i",wiimotes, max_wiimotes); + + //No cleanup needed, less wiimotes available than needed + if (wiimotes <= max_wiimotes) + return 0; + else if (!wm) + return 0; + + for (i = max_wiimotes; i < wiimotes; i++) { + if(wm[i]) { + wiiuse_disconnect(wm[i]); + wm[i]->state = WIIMOTE_INIT_STATES; + wm[i]->flags = WIIUSE_INIT_FLAGS; + wm[i]->event = WIIUSE_NONE; + } + } + return i; + +} + +#endif /* ifdef _WIN32 */ diff --git a/Source/Core/wiiuse/Src/ir.cpp b/Source/Core/wiiuse/Src/ir.cpp new file mode 100644 index 0000000000..f1bcb31bf0 --- /dev/null +++ b/Source/Core/wiiuse/Src/ir.cpp @@ -0,0 +1,135 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles IR data. + */ + +#include <stdio.h> +#include <math.h> + +#ifndef _WIN32 + #include <unistd.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" + +static int get_ir_sens(struct wiimote_t* wm, const char** block1, const char** block2); + +/** + * @brief Get the IR sensitivity settings. + * + * @param wm Pointer to a wiimote_t structure. + * @param block1 [out] Pointer to where block1 will be set. + * @param block2 [out] Pointer to where block2 will be set. + * + * @return Returns the sensitivity level. + */ +static int get_ir_sens(struct wiimote_t* wm, const char** block1, const char** block2) { + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) { + *block1 = WM_IR_BLOCK1_LEVEL1; + *block2 = WM_IR_BLOCK2_LEVEL1; + return 1; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) { + *block1 = WM_IR_BLOCK1_LEVEL2; + *block2 = WM_IR_BLOCK2_LEVEL2; + return 2; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) { + *block1 = WM_IR_BLOCK1_LEVEL3; + *block2 = WM_IR_BLOCK2_LEVEL3; + return 3; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) { + *block1 = WM_IR_BLOCK1_LEVEL4; + *block2 = WM_IR_BLOCK2_LEVEL4; + return 4; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) { + *block1 = WM_IR_BLOCK1_LEVEL5; + *block2 = WM_IR_BLOCK2_LEVEL5; + return 5; + } + + *block1 = NULL; + *block2 = NULL; + return 0; +} + + +/** + * @brief Set the IR sensitivity. + * + * @param wm Pointer to a wiimote_t structure. + * @param level 1-5, same as Wii system sensitivity setting. + * + * If the level is < 1, then level will be set to 1. + * If the level is > 5, then level will be set to 5. + */ +void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) { + const char* block1 = NULL; + const char* block2 = NULL; + + if (!wm) return; + + if (level > 5) level = 5; + if (level < 1) level = 1; + + WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 | + WIIMOTE_STATE_IR_SENS_LVL2 | + WIIMOTE_STATE_IR_SENS_LVL3 | + WIIMOTE_STATE_IR_SENS_LVL4 | + WIIMOTE_STATE_IR_SENS_LVL5)); + + switch (level) { + case 1: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1); + break; + case 2: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2); + break; + case 3: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3); + break; + case 4: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4); + break; + case 5: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5); + break; + default: + return; + } + + /* set the new sensitivity */ + get_ir_sens(wm, &block1, &block2); + + wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); + wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); + + DEBUG_LOG(WIIMOTE, "Set IR sensitivity to level %i (unid %i)", level, wm->unid); +} diff --git a/Source/Core/wiiuse/Src/wiiuse.cpp b/Source/Core/wiiuse/Src/wiiuse.cpp new file mode 100644 index 0000000000..cc45638b4e --- /dev/null +++ b/Source/Core/wiiuse/Src/wiiuse.cpp @@ -0,0 +1,406 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief General wiimote operations. + * + * The file includes functions that handle general + * tasks. Most of these are functions that are part + * of the API. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef _WIN32 + #include <unistd.h> +#else + #include <Winsock2.h> +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" + + +static int g_banner = 1; + +/** + * @breif Returns the version of the library. + */ +const char* wiiuse_version() { + return WIIUSE_VERSION; +} + + +/** + * @brief Clean up wiimote_t array created by wiiuse_init() + */ +void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) { + int i = 0; + + if (!wm) + return; + + NOTICE_LOG(WIIMOTE, "wiiuse clean up..."); + + for (; i < wiimotes; ++i) { + wiiuse_disconnect(wm[i]); + free(wm[i]); + } + + free(wm); + + return; +} + + +/** + * @brief Initialize an array of wiimote structures. + * + * @param wiimotes Number of wiimote_t structures to create. + * + * @return An array of initialized wiimote_t structures. + * + * @see wiiuse_connect() + * + * The array returned by this function can be passed to various + * functions, including wiiuse_connect(). + */ +struct wiimote_t** wiiuse_init(int wiimotes) { + int i = 0; + struct wiimote_t** wm = NULL; + + /* + * Please do not remove this banner. + * GPL asks that you please leave output credits intact. + * Thank you. + * + * This banner is only displayed once so that if you need + * to call this function again it won't be intrusive. + */ + if (!g_banner) { + printf( "wiiuse v" WIIUSE_VERSION " loaded.\n" + " By: Michael Laforest <thepara[at]gmail{dot}com>\n" + " http://wiiuse.net http://wiiuse.sf.net\n"); + g_banner = 1; + } + + if (!wiimotes) + return NULL; + + wm = (struct wiimote_t **)malloc(sizeof(struct wiimote_t*) * wiimotes); + + for (i = 0; i < wiimotes; ++i) { + wm[i] = (struct wiimote_t *)malloc(sizeof(struct wiimote_t)); + memset(wm[i], 0, sizeof(struct wiimote_t)); + + wm[i]->unid = i+1; + + #if defined __linux__ && HAVE_BLUEZ + wm[i]->bdaddr = *BDADDR_ANY; + wm[i]->out_sock = -1; + wm[i]->in_sock = -1; + #elif defined(_WIN32) + wm[i]->dev_handle = 0; + wm[i]->stack = WIIUSE_STACK_UNKNOWN; + #endif + + wm[i]->timeout = WIIMOTE_DEFAULT_TIMEOUT; + wm[i]->state = WIIMOTE_INIT_STATES; + wm[i]->flags = WIIUSE_INIT_FLAGS; + wm[i]->event = WIIUSE_NONE; + } + + return wm; +} + + +/** + * @brief The wiimote disconnected. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_disconnected(struct wiimote_t* wm) { + if (!wm) return; + + NOTICE_LOG(WIIMOTE, "Wiimote disconnected [id %i].", wm->unid); + + /* disable the connected flag */ + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + + /* reset a bunch of stuff */ + wm->leds = 0; + wm->state = WIIMOTE_INIT_STATES; + memset(wm->event_buf, 0, sizeof(wm->event_buf)); + + #if defined __linux__ && HAVE_BLUEZ + wm->out_sock = -1; + wm->in_sock = -1; + #elif defined(_WIN32) + CloseHandle(wm->dev_handle); + wm->dev_handle = 0; + #endif + + wm->event = WIIUSE_DISCONNECT; +} + + +/** + * @brief Enable or disable the rumble. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_rumble(struct wiimote_t* wm, int status) { + byte buf; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + /* make sure to keep the current lit leds */ + buf = wm->leds; + + if (status) { + DEBUG_LOG(WIIMOTE, "Starting rumble..."); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); + buf |= 0x01; + } else { + DEBUG_LOG(WIIMOTE, "Stopping rumble..."); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); + } + + /* preserve IR state */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + buf |= 0x04; + + wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1); +} + +/** + * @brief Set the enabled LEDs. + * + * @param wm Pointer to a wiimote_t structure. + * @param leds What LEDs to enable. + * + * \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4. + */ +void wiiuse_set_leds(struct wiimote_t* wm, int leds) { + byte buf; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + /* remove the lower 4 bits because they control rumble */ + wm->leds = (leds & 0xF0); + buf = wm->leds; + + /* make sure if the rumble is on that we keep it on */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + buf |= 0x01; + + wiiuse_send(wm, WM_CMD_LED, &buf, 1); +} + + +/** + * @brief Set the report type based on the current wiimote state. + * + * @param wm Pointer to a wiimote_t structure. + * + * @return The report type sent. + * + * The wiimote reports formatted packets depending on the + * report type that was last requested. This function will + * update the type of report that should be sent based on + * the current state of the device. + */ +int wiiuse_set_report_type(struct wiimote_t* wm) { + byte buf[2]; + int motion, expansion, ir; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */ + + /* if rumble is enabled, make sure we keep it */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + buf[0] |= 0x01; + + motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC); + expansion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP); + ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR); + + buf[1] = 0x30; + + + DEBUG_LOG(WIIMOTE, "Setting report type: 0x%x", buf[1]); + + expansion = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2); + if (expansion <= 0) + return expansion; + + return buf[1]; +} + + + +/** + * @brief Write data to the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param addr The address to write to. + * @param data The data to be written to the memory location. + * @param len The length of the block to be written. + */ +int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) { + byte buf[21] = {0}; /* the payload is always 23 */ + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + if (!data || !len) + return 0; + + DEBUG_LOG(WIIMOTE, "Writing %i bytes to memory location 0x%x...", len, addr); + + #ifdef WITH_WIIUSE_DEBUG + { + int i = 0; + printf("Write data is: "); + for (; i < len; ++i) + printf("%x ", data[i]); + printf("\n"); + } + #endif + + /* the offset is in big endian */ + *(int*)(buf) = BIG_ENDIAN_LONG(addr); + + /* length */ + *(byte*)(buf + 4) = len; + + /* data */ + memcpy(buf + 5, data, len); + + wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21); + return 1; +} + + +/** + * @brief Send a packet to the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h + * @param msg The payload. + * @param len Length of the payload in bytes. + * + * This function should replace any write()s directly to the wiimote device. + */ +int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) { + byte buf[32]; /* no payload is better than this */ + int rumble = 0; + + buf[0] = WM_SET_REPORT | WM_BT_OUTPUT; + buf[1] = report_type; + + switch (report_type) { + case WM_CMD_LED: + case WM_CMD_RUMBLE: + case WM_CMD_CTRL_STATUS: + { + /* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + rumble = 1; + break; + } + default: + break; + } + + memcpy(buf+2, msg, len); + if (rumble) + buf[2] |= 0x01; + + #ifdef WITH_WIIUSE_DEBUG + { + int x = 2; + printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]); + #ifndef _WIN32 + for (; x < len+2; ++x) + #else + for (; x < len+1; ++x) + #endif + printf("%.2x ", buf[x]); + printf("\n"); + } + #endif + + return wiiuse_io_write(wm, buf, len+2); +} + + + + +/** + * @brief Set the bluetooth stack type to use. + * + * @param wm Array of wiimote_t structures. + * @param wiimotes Number of objects in the wm array. + * @param type The type of bluetooth stack to use. + */ +void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) { + #ifdef _WIN32 + int i; + + if (!wm) return; + + for (i = 0; i < wiimotes; ++i) + wm[i]->stack = type; + #endif +} + +/** + * @brief Set the normal and expansion handshake timeouts. + * + * @param wm Array of wiimote_t structures. + * @param wiimotes Number of objects in the wm array. + * @param normal_timeout The timeout in milliseconds for a normal read. + * @param exp_timeout The timeout in millisecondsd to wait for an expansion handshake. + */ +void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte timeout) { + int i; + + if (!wm) return; + + for (i = 0; i < wiimotes; ++i) { + wm[i]->timeout = timeout; + } +} diff --git a/Source/Core/wiiuse/Src/wiiuse.h b/Source/Core/wiiuse/Src/wiiuse.h new file mode 100644 index 0000000000..a9049b0a59 --- /dev/null +++ b/Source/Core/wiiuse/Src/wiiuse.h @@ -0,0 +1,221 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $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 + #include <windows.h> +#elif defined(__APPLE__) + #include <CoreFoundation/CoreFoundation.h> + #include <IOBluetooth/IOBluetoothUserLib.h> + #include <string.h> +#elif defined(__linux__) + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif + #if HAVE_BLUEZ + #include <bluetooth/bluetooth.h> + #endif +#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 + + +/* 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) + + +/** + * @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_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. + */ +#define WIIMOTE_DEFAULT_TIMEOUT 30 + +typedef unsigned char byte; +typedef char sbyte; + + +/** + * @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; + + +/** + * @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_WII_BOARD_CTRL_INSERTED, + WIIUSE_WII_BOARD_CTRL_REMOVED, + WIIUSE_MOTION_PLUS_INSERTED, + WIIUSE_MOTION_PLUS_REMOVED +} WIIUSE_EVENT_TYPE; + +/** + * @struct wiimote_t + * @brief Wiimote structure. + */ +typedef struct wiimote_t { + WCONST int unid; /**< user specified id */ + + #if defined(__APPLE__) + WCONST IOBluetoothDeviceRef *device; + WCONST char bdaddr_str[18]; + #elif defined(__linux__) && HAVE_BLUEZ + WCONST bdaddr_t bdaddr; /**< bt address (linux) */ + WCONST char bdaddr_str[18]; /**< readable bt address */ + WCONST int out_sock; /**< output socket */ + WCONST int in_sock; /**< input socket */ + #elif defined(_WIN32) + WCONST char devicepath[255]; /**< unique wiimote reference */ + //WCONST ULONGLONG btaddr; /**< bt address (windows) */ + 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 */ + #endif + WCONST int timeout; /**< read timeout */ + WCONST int state; /**< various state flags */ + WCONST byte leds; /**< currently lit leds */ + + WCONST int flags; /**< options flag */ + + WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */ + WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */ +} wiimote; + + +/***************************************** + * + * Include API specific stuff + * + *****************************************/ + +/* wiiuse.c */ +extern const char* wiiuse_version(); + +extern struct wiimote_t** wiiuse_init(int wiimotes); +extern void wiiuse_disconnected(struct wiimote_t* wm); +extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes); +extern void wiiuse_rumble(struct wiimote_t* wm, int status); +extern void wiiuse_set_leds(struct wiimote_t* wm, int leds); +extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len); + +/* connect.c / io_win.c */ +#ifdef _WIN32 +extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int wiimotes); +#else +extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout); +#endif +extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes); +extern void wiiuse_disconnect(struct wiimote_t* wm); +extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte timeout); + +#ifdef _WIN32 +extern int wiiuse_check_system_notification(unsigned int nMsg, WPARAM wParam, LPARAM lParam); +extern int wiiuse_register_system_notification(HWND hwnd); +#endif + +/* ir.c */ +extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); + +/* io.c */ +extern int wiiuse_io_read(struct wiimote_t* wm); +extern int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); + +#endif /* WIIUSE_H_INCLUDED */ + diff --git a/Source/Core/wiiuse/Src/wiiuse_internal.h b/Source/Core/wiiuse/Src/wiiuse_internal.h new file mode 100644 index 0000000000..391bbd89c9 --- /dev/null +++ b/Source/Core/wiiuse/Src/wiiuse_internal.h @@ -0,0 +1,163 @@ +/* + * 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 <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + +/** + * @file + * @brief General internal wiiuse stuff. + * + * Since Wiiuse is a library, wiiuse.h is a duplicate + * of the API header. + * + * The code that would normally go in that file, but + * which is not needed by third party developers, + * is put here. + * + * So wiiuse_internal.h is included by other files + * internally, wiiuse.h is included only here. + */ + +#ifndef WIIUSE_INTERNAL_H_INCLUDED +#define WIIUSE_INTERNAL_H_INCLUDED + +/* wiiuse version */ +#define WIIUSE_VERSION "0.12" + +/******************** + * + * Wiimote internal codes + * + ********************/ + +/* Communication channels */ +#define WM_OUTPUT_CHANNEL 0x11 +#define WM_INPUT_CHANNEL 0x13 + +#define WM_SET_REPORT 0x50 + +/* commands */ +#define WM_CMD_LED 0x11 +#define WM_CMD_REPORT_TYPE 0x12 +#define WM_CMD_RUMBLE 0x13 +#define WM_CMD_IR 0x13 +#define WM_CMD_CTRL_STATUS 0x15 +#define WM_CMD_SPEAKER_ENABLE 0x14// Size 1 +#define WM_CMD_WRITE_DATA 0x16 +#define WM_CMD_READ_DATA 0x17 +#define WM_CMD_SPEAKER_DATA 0x18// Size 21 +#define WM_CMD_SPEAKER_MUTE 0x19// Size 1 +#define WM_CMD_IR_2 0x1A + + +#define WM_BT_INPUT 0x01 +#define WM_BT_OUTPUT 0x02 + +/* Identify the wiimote device by its class */ +#define WM_DEV_CLASS_0 0x04 +#define WM_DEV_CLASS_1 0x25 +#define WM_DEV_CLASS_2 0x00 +#define WM_VENDOR_ID 0x057E +#define WM_PRODUCT_ID 0x0306 + + + +/* offsets in wiimote memory */ +#define WM_MEM_OFFSET_CALIBRATION 0x16 + +#define WM_REG_IR_BLOCK1 0x04B00000 +#define WM_REG_IR_BLOCK2 0x04B0001A + + +/* ir block data */ +#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe" +#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05" +#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4" +#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04" +#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64" +#define WM_IR_BLOCK2_LEVEL3 "\x63\x03" +#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36" +#define WM_IR_BLOCK2_LEVEL4 "\x35\x03" +#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20" +#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03" + +#define WM_IR_TYPE_BASIC 0x01 +#define WM_IR_TYPE_EXTENDED 0x03 +#define WM_IR_TYPE_FULL 0x05 + + + + +/******************** + * + * End Wiimote internal codes + * + ********************/ + +/* wiimote state flags - (some duplicated in wiiuse.h)*/ +#define WIIMOTE_STATE_DEV_FOUND 0x0001 +#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_CONNECTED 0x0008 +#define WIIMOTE_STATE_RUMBLE 0x0010 +#define WIIMOTE_STATE_ACC 0x0020 +#define WIIMOTE_STATE_EXP 0x0040 +#define WIIMOTE_STATE_IR 0x0080 +#define WIIMOTE_STATE_SPEAKER 0x0100 +#define WIIMOTE_STATE_IR_SENS_LVL1 0x0200 +#define WIIMOTE_STATE_IR_SENS_LVL2 0x0400 +#define WIIMOTE_STATE_IR_SENS_LVL3 0x0800 +#define WIIMOTE_STATE_IR_SENS_LVL4 0x1000 +#define WIIMOTE_STATE_IR_SENS_LVL5 0x2000 + +#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3) + +/* macro to manage states */ +#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s)) +#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s)) +#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s)) +#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s)) + +#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s)) +#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s)) +#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s)) +#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s)) + +#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s)) + +/* misc macros */ +#define WIIMOTE_ID(wm) (wm->unid) +#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) + + + +#include "wiiuse.h" + +/* not part of the api */ +int wiiuse_set_report_type(struct wiimote_t* wm); +int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len); + +#endif /* WIIUSE_INTERNAL_H_INCLUDED */ diff --git a/Source/Core/wiiuse/wiiuse.sln b/Source/Core/wiiuse/wiiuse.sln new file mode 100644 index 0000000000..acfb7eec48 --- /dev/null +++ b/Source/Core/wiiuse/wiiuse.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wiiuse", "wiiuse.vcproj", "{52F70249-373A-4401-A70A-FF22760EC1B8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|Win32.ActiveCfg = Debug|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|Win32.Build.0 = Debug|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|x64.ActiveCfg = Debug|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Debug|x64.Build.0 = Debug|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|Win32.ActiveCfg = Release|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|Win32.Build.0 = Release|Win32 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|x64.ActiveCfg = Release|x64 + {52F70249-373A-4401-A70A-FF22760EC1B8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Source/Core/wiiuse/wiiuse.vcproj b/Source/Core/wiiuse/wiiuse.vcproj new file mode 100644 index 0000000000..d9bc4337d6 --- /dev/null +++ b/Source/Core/wiiuse/wiiuse.vcproj @@ -0,0 +1,404 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9.00" + Name="wiiuse" + ProjectGUID="{52F70249-373A-4401-A70A-FF22760EC1B8}" + RootNamespace="wiiuse" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(PlatformName)\$(ConfigurationName)" + IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\Common\Src" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + AdditionalDependencies="setupapi.lib" + OutputFile="$(OutDir)\$(ProjectName).lib" + AdditionalLibraryDirectories="" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Debug|x64" + OutputDirectory="$(PlatformName)\$(ConfigurationName)" + IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TargetEnvironment="3" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\Common\Src" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + AdditionalDependencies="setupapi.lib" + OutputFile="$(OutDir)\$(ProjectName).lib" + AdditionalLibraryDirectories="" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(PlatformName)\$(ConfigurationName)" + IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + AdditionalIncludeDirectories="..\Common\Src" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + AdditionalDependencies="setupapi.lib" + OutputFile="$(OutDir)\$(ProjectName).lib" + AdditionalLibraryDirectories="" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + OutputDirectory="$(PlatformName)\$(ConfigurationName)" + IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TargetEnvironment="3" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + AdditionalIncludeDirectories="..\Common\Src" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + WarningLevel="3" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + AdditionalDependencies="setupapi.lib" + OutputFile="$(OutDir)\$(ProjectName).lib" + AdditionalLibraryDirectories="" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Common" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\Src\definitions.h" + > + </File> + </Filter> + <Filter + Name="I/O" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + <File + RelativePath=".\Src\io_nix.c" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\Src\io_osx.m" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCustomBuildTool" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\Src\io_win.cpp" + > + </File> + </Filter> + <Filter + Name="Wiimote Data" + > + <File + RelativePath=".\Src\ir.cpp" + > + </File> + </Filter> + <File + RelativePath=".\Src\SConscript" + > + </File> + <File + RelativePath=".\Src\wiiuse.cpp" + > + </File> + <File + RelativePath=".\Src\wiiuse.h" + > + </File> + <File + RelativePath=".\Src\wiiuse_internal.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> |
