summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2016-02-07 15:51:33 -0500
committerRyan Houdek <Sonicadvance1@gmail.com>2016-02-07 15:51:33 -0500
commit35d7c2bc78007f550474f035c486bcc5f79ef60f (patch)
tree862050acf1357424dbd0912dc5937ba1b0601393 /Source/Core
parent76d614ededd95deb4e6dea774541d26827d5c4cc (diff)
parentfe53461611d86384478064be6b4297a7c7e437e1 (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.txt2
-rw-r--r--Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp165
-rw-r--r--Source/Core/Core/HW/WiimoteReal/WiimoteReal.h4
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