diff options
| author | Ryan Houdek <Sonicadvance1@gmail.com> | 2016-02-07 15:51:33 -0500 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@gmail.com> | 2016-02-07 15:51:33 -0500 |
| commit | 35d7c2bc78007f550474f035c486bcc5f79ef60f (patch) | |
| tree | 862050acf1357424dbd0912dc5937ba1b0601393 /Source/Core | |
| parent | 76d614ededd95deb4e6dea774541d26827d5c4cc (diff) | |
| parent | fe53461611d86384478064be6b4297a7c7e437e1 (diff) | |
Merge pull request #3593 from Sonicadvance1/Android_Mayflash_adapter
[Android] Implement support for real Wiimotes with the DolphinBar
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp | 165 | ||||
| -rw-r--r-- | Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 4 |
3 files changed, 171 insertions, 0 deletions
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index b035b64859..4fe1353d23 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -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() diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp new file mode 100644 index 0000000000..7a2e1e249c --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp @@ -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)); +} + +} diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index 1ca31a8d69..60c5e38bbb 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -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 |
