1 // Copyright 2016 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4
5 #include <jni.h>
6
7 #include "Common/CommonTypes.h"
8 #include "Common/Event.h"
9 #include "Common/Flag.h"
10 #include "Common/Logging/Log.h"
11 #include "Common/StringUtil.h"
12 #include "Common/Thread.h"
13 #include "Common/Timer.h"
14
15 #include "Core/HW/WiimoteReal/IOAndroid.h"
16
17 #include "jni/AndroidCommon/IDCache.h"
18
19 namespace WiimoteReal
20 {
21 // Java classes
22 static jclass s_adapter_class;
23
FindWiimotes(std::vector<Wiimote * > & found_wiimotes,Wiimote * & found_board)24 void WiimoteScannerAndroid::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
25 Wiimote*& found_board)
26 {
27 found_wiimotes.clear();
28 found_board = nullptr;
29
30 NOTICE_LOG(WIIMOTE, "Finding Wiimotes");
31
32 JNIEnv* env = IDCache::GetEnvForThread();
33
34 jmethodID openadapter_func = env->GetStaticMethodID(s_adapter_class, "OpenAdapter", "()Z");
35 jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z");
36
37 if (env->CallStaticBooleanMethod(s_adapter_class, queryadapter_func) &&
38 env->CallStaticBooleanMethod(s_adapter_class, openadapter_func))
39 {
40 for (int i = 0; i < MAX_WIIMOTES; ++i)
41 found_wiimotes.emplace_back(new WiimoteAndroid(i));
42 }
43 }
44
WiimoteAndroid(int index)45 WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index)
46 {
47 }
48
~WiimoteAndroid()49 WiimoteAndroid::~WiimoteAndroid()
50 {
51 Shutdown();
52 }
53
54 // Connect to a Wiimote with a known address.
ConnectInternal()55 bool WiimoteAndroid::ConnectInternal()
56 {
57 m_env = IDCache::GetEnvForThread();
58
59 jfieldID payload_field = m_env->GetStaticFieldID(s_adapter_class, "wiimote_payload", "[[B");
60 jobjectArray payload_object =
61 reinterpret_cast<jobjectArray>(m_env->GetStaticObjectField(s_adapter_class, payload_field));
62 m_java_wiimote_payload =
63 (jbyteArray)m_env->GetObjectArrayElement(payload_object, m_mayflash_index);
64
65 // Get function pointers
66 m_input_func = m_env->GetStaticMethodID(s_adapter_class, "Input", "(I)I");
67 m_output_func = m_env->GetStaticMethodID(s_adapter_class, "Output", "(I[BI)I");
68
69 is_connected = true;
70
71 return true;
72 }
73
DisconnectInternal()74 void WiimoteAndroid::DisconnectInternal()
75 {
76 }
77
IsConnected() const78 bool WiimoteAndroid::IsConnected() const
79 {
80 return is_connected;
81 }
82
83 // positive = read packet
84 // negative = didn't read packet
85 // zero = error
IORead(u8 * buf)86 int WiimoteAndroid::IORead(u8* buf)
87 {
88 int read_size = m_env->CallStaticIntMethod(s_adapter_class, m_input_func, m_mayflash_index);
89 if (read_size > 0)
90 {
91 jbyte* java_data = m_env->GetByteArrayElements(m_java_wiimote_payload, nullptr);
92 memcpy(buf + 1, java_data, std::min(MAX_PAYLOAD - 1, read_size));
93 buf[0] = 0xA1;
94 m_env->ReleaseByteArrayElements(m_java_wiimote_payload, java_data, 0);
95 }
96 return read_size <= 0 ? read_size : read_size + 1;
97 }
98
IOWrite(u8 const * buf,size_t len)99 int WiimoteAndroid::IOWrite(u8 const* buf, size_t len)
100 {
101 jbyteArray output_array = m_env->NewByteArray(len);
102 jbyte* output = m_env->GetByteArrayElements(output_array, nullptr);
103 memcpy(output, buf, len);
104 m_env->ReleaseByteArrayElements(output_array, output, 0);
105 int written = m_env->CallStaticIntMethod(s_adapter_class, m_output_func, m_mayflash_index,
106 output_array, len);
107 m_env->DeleteLocalRef(output_array);
108 return written;
109 }
110
InitAdapterClass()111 void InitAdapterClass()
112 {
113 JNIEnv* env = IDCache::GetEnvForThread();
114 jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter");
115 s_adapter_class = reinterpret_cast<jclass>(env->NewGlobalRef(adapter_class));
116 }
117 } // namespace WiimoteReal
118