mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 16:49:58 -06:00
Merge pull request #3593 from Sonicadvance1/Android_Mayflash_adapter
[Android] Implement support for real Wiimotes with the DolphinBar
This commit is contained in:
@ -256,6 +256,8 @@ elseif(UNIX)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND BLUEZ_FOUND)
|
||||
set(SRCS ${SRCS} HW/WiimoteReal/IONix.cpp)
|
||||
set(LIBS ${LIBS} bluetooth)
|
||||
elseif(ANDROID)
|
||||
set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp)
|
||||
else()
|
||||
set(SRCS ${SRCS} HW/WiimoteReal/IODummy.cpp)
|
||||
endif()
|
||||
|
165
Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp
Normal file
165
Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||
|
||||
// Global java_vm class
|
||||
extern JavaVM* g_java_vm;
|
||||
|
||||
namespace WiimoteReal
|
||||
{
|
||||
|
||||
// Java classes
|
||||
static jclass s_adapter_class;
|
||||
|
||||
class WiimoteAndroid final : public Wiimote
|
||||
{
|
||||
public:
|
||||
WiimoteAndroid(int index);
|
||||
~WiimoteAndroid() override;
|
||||
|
||||
protected:
|
||||
bool ConnectInternal() override;
|
||||
void DisconnectInternal() override;
|
||||
bool IsConnected() const override;
|
||||
void IOWakeup() {}
|
||||
int IORead(u8* buf) override;
|
||||
int IOWrite(u8 const* buf, size_t len) override;
|
||||
|
||||
private:
|
||||
int m_mayflash_index;
|
||||
bool is_connected = true;
|
||||
|
||||
JNIEnv* m_env;
|
||||
|
||||
jmethodID m_input_func;
|
||||
jmethodID m_output_func;
|
||||
|
||||
jbyteArray m_java_wiimote_payload;
|
||||
};
|
||||
|
||||
WiimoteScanner::WiimoteScanner()
|
||||
{}
|
||||
|
||||
WiimoteScanner::~WiimoteScanner()
|
||||
{}
|
||||
|
||||
void WiimoteScanner::Update()
|
||||
{}
|
||||
|
||||
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board)
|
||||
{
|
||||
found_wiimotes.clear();
|
||||
found_board = nullptr;
|
||||
|
||||
NOTICE_LOG(WIIMOTE, "Finding Wiimotes");
|
||||
|
||||
JNIEnv* env;
|
||||
int get_env_status = g_java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||
|
||||
if (get_env_status == JNI_EDETACHED)
|
||||
g_java_vm->AttachCurrentThread(&env, nullptr);
|
||||
|
||||
jmethodID openadapter_func = env->GetStaticMethodID(s_adapter_class, "OpenAdapter", "()Z");
|
||||
jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z");
|
||||
|
||||
if (env->CallStaticBooleanMethod(s_adapter_class, queryadapter_func) &&
|
||||
env->CallStaticBooleanMethod(s_adapter_class, openadapter_func))
|
||||
{
|
||||
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
found_wiimotes.emplace_back(new WiimoteAndroid(i));
|
||||
}
|
||||
|
||||
if (get_env_status == JNI_EDETACHED)
|
||||
g_java_vm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
bool WiimoteScanner::IsReady() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
WiimoteAndroid::WiimoteAndroid(int index)
|
||||
: Wiimote(), m_mayflash_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
WiimoteAndroid::~WiimoteAndroid()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
// Connect to a Wiimote with a known address.
|
||||
bool WiimoteAndroid::ConnectInternal()
|
||||
{
|
||||
g_java_vm->AttachCurrentThread(&m_env, nullptr);
|
||||
|
||||
jfieldID payload_field = m_env->GetStaticFieldID(s_adapter_class, "wiimote_payload", "[[B");
|
||||
jobjectArray payload_object = reinterpret_cast<jobjectArray>(m_env->GetStaticObjectField(s_adapter_class, payload_field));
|
||||
m_java_wiimote_payload = (jbyteArray)m_env->GetObjectArrayElement(payload_object, m_mayflash_index);
|
||||
|
||||
// Get function pointers
|
||||
m_input_func = m_env->GetStaticMethodID(s_adapter_class, "Input", "(I)I");
|
||||
m_output_func = m_env->GetStaticMethodID(s_adapter_class, "Output", "(I[BI)I");
|
||||
|
||||
is_connected = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WiimoteAndroid::DisconnectInternal()
|
||||
{
|
||||
g_java_vm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
bool WiimoteAndroid::IsConnected() const
|
||||
{
|
||||
return is_connected;
|
||||
}
|
||||
|
||||
// positive = read packet
|
||||
// negative = didn't read packet
|
||||
// zero = error
|
||||
int WiimoteAndroid::IORead(u8* buf)
|
||||
{
|
||||
int read_size = m_env->CallStaticIntMethod(s_adapter_class, m_input_func, m_mayflash_index);
|
||||
jbyte* java_data = m_env->GetByteArrayElements(m_java_wiimote_payload, nullptr);
|
||||
memcpy(buf + 1, java_data, std::min(MAX_PAYLOAD - 1, read_size));
|
||||
buf[0] = 0xA1;
|
||||
m_env->ReleaseByteArrayElements(m_java_wiimote_payload, java_data, 0);
|
||||
return read_size <= 0 ? read_size : read_size + 1;
|
||||
}
|
||||
|
||||
|
||||
int WiimoteAndroid::IOWrite(u8 const* buf, size_t len)
|
||||
{
|
||||
jbyteArray output_array = m_env->NewByteArray(len);
|
||||
jbyte* output = m_env->GetByteArrayElements(output_array, nullptr);
|
||||
memcpy(output, buf, len);
|
||||
m_env->ReleaseByteArrayElements(output_array, output, 0);
|
||||
int written = m_env->CallStaticIntMethod(s_adapter_class, m_output_func, m_mayflash_index, output_array, len);
|
||||
m_env->DeleteLocalRef(output_array);
|
||||
return written;
|
||||
}
|
||||
|
||||
void InitAdapterClass()
|
||||
{
|
||||
JNIEnv* env;
|
||||
g_java_vm->AttachCurrentThread(&env, nullptr);
|
||||
|
||||
jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter");
|
||||
s_adapter_class = reinterpret_cast<jclass>(env->NewGlobalRef(adapter_class));
|
||||
}
|
||||
|
||||
}
|
@ -161,4 +161,8 @@ void ChangeWiimoteSource(unsigned int index, int source);
|
||||
bool IsValidBluetoothName(const std::string& name);
|
||||
bool IsBalanceBoardName(const std::string& name);
|
||||
|
||||
#ifdef ANDROID
|
||||
void InitAdapterClass();
|
||||
#endif
|
||||
|
||||
} // WiimoteReal
|
||||
|
Reference in New Issue
Block a user