Remove wiiuse, and use our own code. Works on linux and windows. On OSX it should compile, but I don't know about functionality. Even on linux and windows I can't promise this is bug free (wiiuse certainly wasn't). Please report issues as you find them for all platforms.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6693 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Glenn Rice
2010-12-31 02:10:07 +00:00
parent b038df64bf
commit 8e184171e7
28 changed files with 1440 additions and 2861 deletions
+2 -3
View File
@@ -124,7 +124,7 @@ else()
message("ao NOT found, disabling ao sound backend")
endif(AO_FOUND)
check_lib(BLUEZ bluez QUIET)
#check_lib(BLUEZ bluez QUIET)
if(BLUEZ_FOUND)
add_definitions(-DHAVE_BLUEZ=1)
message("bluez found, enabling bluetooth support")
@@ -221,7 +221,6 @@ include_directories(Source/Core/InputCommon/Src)
include_directories(Source/Core/InputUICommon/Src)
include_directories(Source/Core/VideoCommon/Src)
include_directories(Source/Core/VideoUICommon/Src)
include_directories(Source/Core/wiiuse/Src)
########################################
@@ -232,7 +231,7 @@ include_directories(Source/Core/wiiuse/Src)
# - make sure to tell cmake to link them statically or dynamically (most
# should be linked statically)
# - place the CMakeLists.txt in the first-level subdirectory, e.g.
# Externals/WiiUse/CMakeLists.txt (that is: NOT in some Src/ subdirectory)
# Externals/CLRun/CMakeLists.txt (that is: NOT in some Src/ subdirectory)
#
add_subdirectory(Externals/Bochs_disasm)
include_directories(Externals/Bochs_disasm)
-1
View File
@@ -359,7 +359,6 @@ dirs = [
'Source/Core/InputUICommon/Src',
'Source/Core/VideoCommon/Src',
'Source/Core/VideoUICommon/Src',
'Source/Core/wiiuse/Src',
'Source/DSPTool/Src',
'Source/Plugins/Plugin_DSP_HLE/Src',
'Source/Plugins/Plugin_DSP_LLE/Src',
-1
View File
@@ -14,4 +14,3 @@ add_subdirectory(DolphinWX)
add_subdirectory(DSPCore)
add_subdirectory(InputCommon)
add_subdirectory(VideoCommon)
add_subdirectory(wiiuse)
+11 -4
View File
@@ -132,16 +132,23 @@ set(SRCS Src/ActionReplay.cpp
Src/PowerPC/JitCommon/JitCache.cpp
Src/PowerPC/JitCommon/Jit_Util.cpp)
set(LIBS bdisasm inputcommon lua sfml-network)
if(WIN32)
set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Win32.cpp Src/stdafx.cpp)
set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Win32.cpp Src/stdafx.cpp
Src/HW/WiimoteReal/IOWin.cpp)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Apple.cpp)
set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Apple.cpp Src/HW/WiimoteReal/IOOsx.mm)
elseif(UNIX)
set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Unix.cpp)
if((${CMAKE_SYSTEM_NAME} MATCHES "Linux") AND BLUEZ_FOUND)
set(SRCS ${SRCS} Src/HW/WiimoteReal/IONix.cpp)
set(LIBS ${LIBS} bluetooth)
else()
set(SRCS ${SRCS} Src/HW/WiimoteReal/IODummy.cpp)
endif()
endif()
set(LIBS bdisasm inputcommon lua sfml-network wiiuse)
if(PORTAUDIO_FOUND)
set(LIBS ${LIBS} portaudio)
endif(PORTAUDIO_FOUND)
+15 -6
View File
@@ -45,7 +45,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
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"
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"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -115,7 +115,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
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"
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"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@@ -189,7 +189,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
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"
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"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
RuntimeLibrary="0"
@@ -266,7 +266,7 @@
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
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"
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"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
RuntimeLibrary="0"
@@ -290,6 +290,7 @@
/>
<Tool
Name="VCLibrarianTool"
AdditionalDependencies="setupapi.lib"
OutputFile="$(OutDir)/Core.lib"
AdditionalLibraryDirectories="&quot;..\..\..\Externals\LZO\$(OutDir)\lzo.lib&quot;"
/>
@@ -340,7 +341,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
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"
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"
PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="true"
@@ -414,7 +415,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
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"
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"
PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
@@ -904,6 +905,10 @@
<Filter
Name="Real"
>
<File
RelativePath=".\Src\HW\WiimoteReal\IOWin.cpp"
>
</File>
<File
RelativePath=".\Src\HW\WiimoteReal\WiimoteReal.cpp"
>
@@ -912,6 +917,10 @@
RelativePath=".\Src\HW\WiimoteReal\WiimoteReal.h"
>
</File>
<File
RelativePath=".\Src\HW\WiimoteReal\WiimoteRealBase.h"
>
</File>
</Filter>
</Filter>
</Filter>
@@ -0,0 +1,49 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "WiimoteReal.h"
namespace WiimoteReal
{
int FindWiimotes(Wiimote **wm, int max_wiimotes)
{
return 0;
}
bool Wiimote::Connect()
{
return 0;
}
void Wiimote::RealDisconnect()
{
return;
}
u8 *Wiimote::IORead()
{
return NULL;
}
int Wiimote::IOWrite(unsigned char* buf, int len)
{
return 0;
}
};
@@ -0,0 +1,258 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#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 "Common.h"
#include "WiimoteReal.h"
// 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
namespace WiimoteReal
{
// Find wiimotes.
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found wiimotes.
int FindWiimotes(Wiimote** wm, int max_wiimotes)
{
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 (wm[i])
found_wiimotes++;
}
// Get the id of the first bluetooth device.
if ((device_id = hci_get_route(NULL)) < 0)
{
NOTICE_LOG(WIIMOTE, "Bluetooth not found.");
return found_wiimotes;
}
// Create a socket to the device
if ((device_sock = hci_open_dev(device_id)) < 0)
{
ERROR_LOG(WIIMOTE, "Unable to open bluetooth.");
return found_wiimotes;
}
int try_num = 0;
while ((try_num < 5) && (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 approximately one second
found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
if (found_devices < 0)
{
ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices.");
return found_wiimotes;
}
DEBUG_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))
{
bool new_wiimote = true;
// Determine if this wiimote has already been found.
for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j)
{
if (wm[j] && bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0)
new_wiimote = false;
}
if (new_wiimote)
{
// Find an unused slot
unsigned int k = 0;
for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k);
wm[k] = new Wiimote(k);
// Found a new device
char bdaddr_str[18];
ba2str(&scan_info[i].bdaddr, bdaddr_str);
NOTICE_LOG(WIIMOTE, "Found wiimote %i, (%s).",
wm[k]->index + 1, bdaddr_str);
wm[k]->bdaddr = scan_info[i].bdaddr;
++found_wiimotes;
}
}
}
try_num++;
}
close(device_sock);
return found_wiimotes;
}
// Connect to a wiimote with a known address.
bool Wiimote::Connect()
{
struct sockaddr_l2 addr;
if (IsConnected()) return false;
addr.l2_family = AF_BLUETOOTH;
addr.l2_bdaddr = bdaddr;
addr.l2_cid = 0;
// Output channel
addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
if ((out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
connect(out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote.");
close(out_sock);
out_sock = -1;
return false;
}
// Input channel
addr.l2_psm = htobs(WM_INPUT_CHANNEL);
if ((in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 ||
connect(in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote.");
close(in_sock);
close(out_sock);
in_sock = out_sock = -1;
return false;
}
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1);
m_connected = true;
// Do the handshake
Handshake();
// Set LEDs
SetLEDs(WIIMOTE_LED_1 << index);
return true;
}
// Disconnect a wiimote.
void Wiimote::RealDisconnect()
{
if (!IsConnected())
return;
NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i.", index + 1);
m_connected = false;
close(out_sock);
close(in_sock);
out_sock = -1;
in_sock = -1;
}
unsigned char *Wiimote::IORead()
{
struct timeval tv;
fd_set fds;
int r;
if (!IsConnected())
return NULL;
// Block select for 1/2000th of a second
tv.tv_sec = 0;
tv.tv_usec = WIIMOTE_DEFAULT_TIMEOUT * 1000;
FD_ZERO(&fds);
FD_SET(in_sock, &fds);
if (select(in_sock + 1, &fds, NULL, NULL, &tv) == -1)
{
ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", index + 1);
return NULL;
}
if (!FD_ISSET(in_sock, &fds))
return NULL;
// Read the pending message into the buffer
unsigned char *buffer = new unsigned char[MAX_PAYLOAD];
r = read(in_sock, buffer, sizeof(buffer));
if (r == -1)
{
// Error reading data
ERROR_LOG(WIIMOTE, "Receiving data from wiimote %i.", index + 1);
if (errno == ENOTCONN)
{
// This can happen if the bluetooth dongle is disconnected
ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. "
"Wiimote %i will be disconnected.", index + 1);
RealDisconnect();
}
delete[] buffer;
return NULL;
}
if (!r)
{
// Disconnect
RealDisconnect();
delete[] buffer;
return NULL;
}
return buffer;
}
int Wiimote::IOWrite(unsigned char* buf, int len)
{
return write(out_sock, buf, len);
}
}; // WiimoteReal
@@ -0,0 +1,298 @@
#import <CoreServices/CoreServices.h>
extern "C" OSErr UpdateSystemActivity(UInt8 activity);
#define BLUETOOTH_VERSION_USE_CURRENT
#import <IOBluetooth/IOBluetooth.h>
#include "Common.h"
#include "../Wiimote.h"
#include "WiimoteReal.h"
@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: (unsigned char *) data
length: (NSUInteger) length
{
IOBluetoothDevice *device = [l2capChannel getDevice];
WiimoteReal::Wiimote *wm = NULL;
for (int i = 0; i < MAX_WIIMOTES; i++)
{
if (WiimoteReal::g_wiimotes[i] == NULL)
continue;
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
wm = WiimoteReal::g_wiimotes[i];
}
if (wm == NULL)
{
WARN_LOG(WIIMOTE, "Received packet for unknown wiimote");
return;
}
if (length > MAX_PAYLOAD)
{
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, too large",
wm->index + 1);
return;
}
if (wm->queue[wm->writer].len != 0)
{
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, queue full",
wm->index + 1);
return;
}
memcpy(wm->queue[wm->writer].data, data, length);
wm->queue[wm->writer].len = length;
wm->writer++;
wm->outstanding++;
if (wm->writer == QUEUE_SIZE)
wm->writer = 0;
if (wm->outstanding > wm->watermark)
{
wm->watermark = wm->outstanding;
WARN_LOG(WIIMOTE, "New queue watermark %i for wiimote %i",
wm->watermark, wm->index + 1);
}
CFRunLoopStop(CFRunLoopGetCurrent());
(void)UpdateSystemActivity(1);
}
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
{
IOBluetoothDevice *device = [l2capChannel getDevice];
WiimoteReal::Wiimote *wm = NULL;
for (int i = 0; i < MAX_WIIMOTES; i++)
{
if (WiimoteReal::g_wiimotes[i] == NULL)
continue;
if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE)
wm = WiimoteReal::g_wiimotes[i];
}
if (wm == NULL)
{
WARN_LOG(WIIMOTE, "Received packet for unknown wiimote");
return;
}
WARN_LOG(WIIMOTE, "L2CAP channel was closed for wiimote %i", wm->index + 1);
if (l2capChannel == wm->cchan)
wm->cchan = nil;
if (l2capChannel == wm->ichan)
wm->ichan = nil;
}
@end
namespace WiimoteReal
{
// Find wiimotes.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found wiimotes.
int FindWiimotes(Wiimote** wm, int max_wiimotes)
{
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
int found_devices = 0, found_wiimotes = 0;
// Count the number of already found wiimotes
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
if (wm[i])
found_wiimotes++;
}
bth = [[IOBluetoothHostController alloc] init];
if ([bth addressAsString] == nil)
{
WARN_LOG(WIIMOTE, "No bluetooth host controller");
[bth release];
return found_wiimotes;
}
sbt = [[SearchBT alloc] init];
sbt->maxDevices = max_wiimotes;
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
[bti setInquiryLength: 5];
[bti setSearchCriteria: kBluetoothServiceClassMajorAny
majorDeviceClass: kBluetoothDeviceClassMajorPeripheral
minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick
];
[bti setUpdateNewDeviceNames: FALSE];
if ([bti start] == 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%c", found_devices,
found_devices == 1 ? '\0' : 's');
en = [[bti foundDevices] objectEnumerator];
for (int i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); i++)
{
IOBluetoothDevice *tmp_btd = [en nextObject];
bool new_wiimote = true;
// Determine if this wiimote has already been found.
for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j)
{
if (wm[j] && [tmp_btd isEqual: wm[j]->btd] == TRUE)
new_wiimote = false;
}
if (new_wiimote)
{
// Find an unused slot
unsigned int k = 0;
for ( ; k < MAX_WIIMOTES &&
!(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k)
{};
wm[k] = new Wiimote(k);
wm[k]->btd = tmp_btd;
found_wiimotes++;
}
}
[bth release];
[bti release];
[sbt release];
return found_wiimotes;
}
// Connect to a wiimote with a known address.
bool Wiimote::Connect()
{
ConnectBT *cbt = [[ConnectBT alloc] init];
if (IsConnected()) return false;
[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 for wiimote %i",
index + 1);
RealDisconnect();
return false;
}
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
index + 1, [[btd getAddressString] UTF8String]);
m_connected = true;
Handshake();
SetLEDs(WIIMOTE_LED_1 << index);
[cbt release];
return true;
}
// Disconnect a wiimote.
void Wiimote::RealDisconnect()
{
if (!IsConnected())
return;
NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1);
m_connected = false;
[cchan closeChannel];
[ichan closeChannel];
[btd closeConnection];
}
unsigned char *Wiimote::IORead()
{
int bytes;
if (!IsConnected())
return NULL;
if (outstanding == 0)
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, true);
if (queue[reader].len == 0)
return 0;
bytes = queue[reader].len;
unsigned char *buffer = new unsigned char[MAX_PAYLOAD];
memcpy(buffer, queue[reader].data, bytes);
queue[reader].len = 0;
reader++;
outstanding--;
if (reader == QUEUE_SIZE)
reader = 0;
if (buffer[0] == '\0')
bytes = 0;
return buffer;
}
int Wiimote::IOWrite(unsigned char* buf, int len)
{
IOReturn ret;
ret = [cchan writeAsync: buf length: len refcon: nil];
if (ret == kIOReturnSuccess)
return len;
else
return 0;
}
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -19,7 +19,7 @@
#ifndef WIIMOTE_REAL_H
#define WIIMOTE_REAL_H
#include "wiiuse.h"
#include "WiimoteRealBase.h"
#include "ChunkFile.h"
#include "Thread.h"
#include "FifoQueue.h"
@@ -43,38 +43,73 @@ namespace WiimoteReal
class Wiimote
{
friend class WiimoteEmu::Wiimote;
public:
Wiimote(wiimote_t* const wm, const unsigned int index);
~Wiimote();
public:
Wiimote(const unsigned int _index);
~Wiimote();
void ControlChannel(const u16 channel, const void* const data, const u32 size);
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
void Update();
void ControlChannel(const u16 channel, const void* const data, const u32 size);
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
void Update();
u8* ProcessReadQueue();
u8* ProcessReadQueue();
bool Read();
bool Write();
void Disconnect();
void DisableDataReporting();
bool Read();
bool Write();
bool Connect();
bool IsConnected();
void Disconnect();
void DisableDataReporting();
void Rumble();
void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size);
void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size);
// Pointer to data, and size of data
typedef std::pair<u8*,u8> Report;
// pointer to data, and size of data
typedef std::pair<u8*,u8> Report;
const unsigned int index;
const unsigned int index;
wiimote_t* const wiimote;
#if defined(__APPLE__)
IOBluetoothDevice *btd;
IOBluetoothL2CAPChannel *ichan;
IOBluetoothL2CAPChannel *cchan;
#define QUEUE_SIZE 64
struct qbuffer
{
char data[MAX_PAYLOAD];
int len;
} queue[QUEUE_SIZE];
int reader;
int writer;
int outstanding;
int watermark;
#elif defined(__linux__) && HAVE_BLUEZ
bdaddr_t bdaddr; // Bluetooth address
int out_sock; // Output socket
int in_sock; // Input socket
#elif defined(_WIN32)
char devicepath[255]; // Unique wiimote reference
//ULONGLONG btaddr; // Bluetooth address
HANDLE dev_handle; // HID handle
OVERLAPPED hid_overlap; // Overlap handle
enum win_bt_stack_t stack; // Type of bluetooth stack to use
#endif
unsigned char leds; // Currently lit leds
protected:
u8 *m_last_data_report;
u16 m_channel;
protected:
u8 *m_last_data_report;
u16 m_channel;
private:
void ClearReadQueue();
private:
void ClearReadQueue();
void RealDisconnect();
bool SendRequest(unsigned char report_type, unsigned char* data, int length);
bool Handshake();
void SetLEDs(int leds);
unsigned char *IORead();
int IOWrite(unsigned char* buf, int len);
Common::FifoQueue<u8*> m_read_reports;
Common::FifoQueue<Report> m_write_reports;
bool m_connected;
Common::FifoQueue<u8*> m_read_reports;
Common::FifoQueue<Report> m_write_reports;
};
extern Common::CriticalSection g_refresh_critsec;
@@ -87,6 +122,8 @@ void Update(int _WiimoteNumber);
void DoState(PointerWrap &p);
void StateChange(PLUGIN_EMUSTATE newState);
}; // WiiMoteReal
int FindWiimotes(Wiimote** wm, int max_wiimotes);
}; // WiimoteReal
#endif
@@ -0,0 +1,75 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef WIIMOTE_COMM_H
#define WIIMOTE_COMM_H
#ifdef _WIN32
#include <windows.h>
#elif defined(__APPLE__)
#import <IOBluetooth/IOBluetooth.h>
#elif defined(__linux__) && HAVE_BLUEZ
#include <bluetooth/bluetooth.h>
#endif
// Wiimote internal codes
// Communication channels
#define WM_OUTPUT_CHANNEL 0x11
#define WM_INPUT_CHANNEL 0x13
#define WM_SET_REPORT 0x50
// Commands
#define WM_CMD_RUMBLE 0x10
#define WM_CMD_LED 0x11
#define WM_CMD_REPORT_TYPE 0x12
#define WM_CMD_IR 0x13
#define WM_CMD_SPEAKER_ENABLE 0x14
#define WM_CMD_CTRL_STATUS 0x15
#define WM_CMD_WRITE_DATA 0x16
#define WM_CMD_READ_DATA 0x17
#define WM_CMD_SPEAKER_DATA 0x18
#define WM_CMD_SPEAKER_MUTE 0x19
#define WM_CMD_IR_2 0x1A
#define WM_BT_INPUT 0x01
#define WM_BT_OUTPUT 0x02
// 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
// End Wiimote internal codes
#define MAX_PAYLOAD 32
#define WIIMOTE_DEFAULT_TIMEOUT 30
#ifdef _WIN32
// Available bluetooth stacks for Windows.
typedef enum win_bt_stack_t
{
MSBT_STACK_UNKNOWN,
MSBT_STACK_MS,
MSBT_STACK_BLUESOLEIL
} win_bt_stack_t;
#endif
#endif // WIIMOTE_COMM_H
+3 -3
View File
@@ -146,10 +146,10 @@ libs = [
]
if sys.platform == 'win32':
files += [ "HW/BBA-TAP/TAP_Win32.cpp", "stdafx.cpp" ]
files += [ "HW/BBA-TAP/TAP_Win32.cpp", "stdafx.cpp", "HW/WiimoteReal/IOWin.cpp" ]
elif sys.platform == 'darwin':
files += [ "HW/BBA-TAP/TAP_Apple.cpp" ]
files += [ "HW/BBA-TAP/TAP_Apple.cpp", "HW/WiimoteReal/IOOsx.mm" ]
else:
files += [ "HW/BBA-TAP/TAP_Unix.cpp" ]
files += [ "HW/BBA-TAP/TAP_Unix.cpp", "HW/WiimoteReal/IONix.cpp" ]
env.StaticLibrary(env['local_libs'] + 'core', files, LIBS = libs)
-1
View File
@@ -9,7 +9,6 @@ set(LIBS core
lua
z
sfml-network
wiiuse
SDL
GL
${XRANDR_LIBRARIES}
+1 -1
View File
@@ -11,7 +11,7 @@ files = [
libs = [
'core', 'lzo2', 'discio', 'bdisasm',
'inputcommon', 'common', 'lua', 'z', 'sfml-network', 'wiiuse',
'inputcommon', 'common', 'lua', 'z', 'sfml-network',
]
if env['HAVE_WX']:
-16
View File
@@ -1,16 +0,0 @@
set(SRCS Src/ir.cpp
Src/wiiuse.cpp)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SRCS ${SRCS} Src/io_osx.m)
elseif((${CMAKE_SYSTEM_NAME} MATCHES "Linux") 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})
-20
View File
@@ -1,20 +0,0 @@
# -*- python -*-
Import('env')
import sys
files = [
"ir.cpp",
"wiiuse.cpp",
]
if sys.platform == 'darwin':
files += [ "io_osx.mm" ]
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)
-27
View File
@@ -1,27 +0,0 @@
#include "Common.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;
}
-329
View File
@@ -1,329 +0,0 @@
/*
* 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 "Common.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
{
bdaddr_t bdaddr_any = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
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);
}
-360
View File
@@ -1,360 +0,0 @@
/*
* 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 "C" OSErr UpdateSystemActivity(UInt8 activity);
#define BLUETOOTH_VERSION_USE_CURRENT
#import <IOBluetooth/IOBluetooth.h>
#include "Common.h"
#include "HW/Wiimote.h"
#include "wiiuse_internal.h"
static int wiiuse_connect_single(struct wiimote_t *wm, char *address);
static struct wiimote_t *motes[MAX_WIIMOTES];
@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];
struct wiimote_t *wm = NULL;
for (int i = 0; i < MAX_WIIMOTES; i++) {
if (motes[i] == NULL)
continue;
if ([device isEqual: motes[i]->btd] == TRUE)
wm = motes[i];
if (i == MAX_WIIMOTES && wm == NULL) {
WARN_LOG(WIIMOTE, "Received packet for unknown wiimote");
return;
}
}
if (length > MAX_PAYLOAD) {
WARN_LOG(WIIMOTE, "Dropping wiimote packet, too large [id %i]",
wm->unid);
return;
}
if (wm->queue[wm->writer].len != 0) {
WARN_LOG(WIIMOTE, "Dropping wiimote packet, queue full [id %i]",
wm->unid);
return;
}
memcpy(wm->queue[wm->writer].data, data, length);
wm->queue[wm->writer].len = length;
wm->writer++;
wm->outstanding++;
if (wm->writer == QUEUE_SIZE)
wm->writer = 0;
if (wm->outstanding > wm->watermark) {
wm->watermark = wm->outstanding;
WARN_LOG(WIIMOTE, "New wiimote queue watermark %i [id %i]",
wm->watermark, wm->unid);
}
CFRunLoopStop(CFRunLoopGetCurrent());
(void)UpdateSystemActivity(1);
}
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
{
IOBluetoothDevice *device = [l2capChannel getDevice];
struct wiimote_t *wm = NULL;
for (int i = 0; i < MAX_WIIMOTES; i++) {
if (motes[i] == NULL)
continue;
if ([device isEqual: motes[i]->btd] == TRUE)
wm = motes[i];
if (i == MAX_WIIMOTES && wm == NULL) {
WARN_LOG(WIIMOTE, "Received packet for unknown wiimote");
return;
}
}
WARN_LOG(WIIMOTE, "L2CAP channel was closed [id %i]", wm->unid);
if (l2capChannel == wm->cchan)
wm->cchan = nil;
if (l2capChannel == wm->ichan)
wm->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)
{
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
int i, found_devices = 0;
if (max_wiimotes > MAX_WIIMOTES)
return 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;
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
[bti setInquiryLength: timeout];
[bti setSearchCriteria: kBluetoothServiceClassMajorAny
majorDeviceClass: kBluetoothDeviceClassMajorPeripheral
minorDeviceClass: kBluetoothDeviceClassMinorPeripheral2Joystick
];
[bti setUpdateNewDeviceNames: FALSE];
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%c", found_devices,
found_devices == 1 ? '\0' : 's');
en = [[bti foundDevices] objectEnumerator];
for (i = 0; i < found_devices; i++) {
wm[i]->btd = [en nextObject];
WIIMOTE_ENABLE_STATE(wm[i], WIIMOTE_STATE_DEV_FOUND);
motes[i] = wm[i];
}
for (i = found_devices; i < MAX_WIIMOTES; i++)
motes[i] = NULL;
[bth release];
[bti release];
[sbt 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)
{
ConnectBT *cbt = [[ConnectBT alloc] init];
if (wm == NULL || WIIMOTE_IS_CONNECTED(wm))
return 0;
[wm->btd openL2CAPChannelSync: &wm->cchan
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
[wm->btd openL2CAPChannelSync: &wm->ichan
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
if (wm->ichan == NULL || wm->cchan == NULL) {
ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels [id %i]",
wm->unid);
wiiuse_disconnect(wm);
}
NOTICE_LOG(WIIMOTE, "Connected to wiimote at %s [id %i]",
[[wm->btd getAddressString] UTF8String], wm->unid);
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
wiiuse_set_report_type(wm);
[cbt 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)
{
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);
[wm->cchan closeChannel];
[wm->ichan closeChannel];
[wm->btd closeConnection];
}
int wiiuse_io_read(struct wiimote_t *wm)
{
int bytes;
if (!WIIMOTE_IS_CONNECTED(wm))
return 0;
if (wm->outstanding == 0)
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, true);
if (wm->queue[wm->reader].len == 0)
return 0;
bytes = wm->queue[wm->reader].len;
memcpy(wm->event_buf, wm->queue[wm->reader].data, bytes);
wm->queue[wm->reader].len = 0;
wm->reader++;
wm->outstanding--;
if (wm->reader == QUEUE_SIZE)
wm->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 = [wm->cchan writeAsync: buf length: len refcon: nil];
if (ret == kIOReturnSuccess)
return len;
else
return 0;
}

Some files were not shown because too many files have changed in this diff Show More