summaryrefslogtreecommitdiff
path: root/Source/Android
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/Android
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/Android')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java5
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java6
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java156
-rw-r--r--Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml5
-rw-r--r--Source/Android/app/src/main/res/values/strings.xml1
-rw-r--r--Source/Android/jni/MainAndroid.cpp7
6 files changed, 180 insertions, 0 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
index 38ea670f5e..992b670b1f 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -380,6 +380,11 @@ public final class NativeLibrary
public static native void eglBindAPI(int api);
/**
+ * Provides a way to refresh the connections on Wiimotes
+ */
+ public static native void RefreshWiimotes();
+
+ /**
* The methods C++ uses to find references to Java classes and methods
* are really expensive. Rather than calling them every time we want to
* run them, do it once when we load the native library.
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
index 2f38df3373..f90956dd9a 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
@@ -33,6 +33,7 @@ import org.dolphinemu.dolphinemu.fragments.SaveStateFragment;
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
import org.dolphinemu.dolphinemu.utils.Animations;
import org.dolphinemu.dolphinemu.utils.Java_GCAdapter;
+import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter;
import org.dolphinemu.dolphinemu.utils.Log;
import java.util.List;
@@ -120,6 +121,7 @@ public final class EmulationActivity extends AppCompatActivity
super.onCreate(savedInstanceState);
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
+ Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
// Picasso will take a while to load these big-ass screenshots. So don't run
// the animation until we say so.
@@ -392,6 +394,10 @@ public final class EmulationActivity extends AppCompatActivity
return;
}
+ case R.id.menu_refresh_wiimotes:
+ NativeLibrary.RefreshWiimotes();
+ return;
+
// Screenshot capturing
case R.id.menu_emulation_screenshot:
NativeLibrary.SaveScreenShot();
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java
new file mode 100644
index 0000000000..049f930cba
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java
@@ -0,0 +1,156 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.hardware.usb.UsbConfiguration;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbDeviceConnection;
+import android.hardware.usb.UsbEndpoint;
+import android.hardware.usb.UsbInterface;
+import android.hardware.usb.UsbManager;
+
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.services.USBPermService;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class Java_WiimoteAdapter
+{
+ final static int MAX_PAYLOAD = 23;
+ final static int MAX_WIIMOTES = 4;
+ final static int TIMEOUT = 200;
+ final static short NINTENDO_VENDOR_ID = 0x057e;
+ final static short NINTENDO_WIIMOTE_PRODUCT_ID = 0x0306;
+ public static UsbManager manager;
+
+ static UsbDeviceConnection usb_con;
+ static UsbInterface[] usb_intf = new UsbInterface[MAX_WIIMOTES];
+ static UsbEndpoint[] usb_in = new UsbEndpoint[MAX_WIIMOTES];
+
+ public static byte[][] wiimote_payload = new byte[MAX_WIIMOTES][MAX_PAYLOAD];
+
+ private static void RequestPermission()
+ {
+ HashMap<String, UsbDevice> devices = manager.getDeviceList();
+ for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
+ {
+ UsbDevice dev = (UsbDevice) pair.getValue();
+ if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
+ {
+ if (!manager.hasPermission(dev))
+ {
+ Log.warning("Requesting permission for Wiimote adapter");
+ Intent intent = new Intent();
+ PendingIntent pend_intent;
+ intent.setClass(NativeLibrary.sEmulationActivity, USBPermService.class);
+ pend_intent = PendingIntent.getService(NativeLibrary.sEmulationActivity, 0, intent, 0);
+ manager.requestPermission(dev, pend_intent);
+ }
+ }
+ }
+ }
+
+ public static boolean QueryAdapter()
+ {
+ HashMap<String, UsbDevice> devices = manager.getDeviceList();
+ for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
+ {
+ UsbDevice dev = (UsbDevice) pair.getValue();
+ if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
+ {
+ if (manager.hasPermission(dev))
+ return true;
+ else
+ RequestPermission();
+ }
+ }
+ return false;
+ }
+
+ public static int Input(int index)
+ {
+ return usb_con.bulkTransfer(usb_in[index], wiimote_payload[index], MAX_PAYLOAD, TIMEOUT);
+ }
+
+ public static int Output(int index, byte[] buf, int size)
+ {
+ byte report_number = buf[0];
+
+ // Remove the report number from the buffer
+ buf = Arrays.copyOfRange(buf, 1, buf.length);
+ size--;
+
+ final int LIBUSB_REQUEST_TYPE_CLASS = (1 << 5);
+ final int LIBUSB_RECIPIENT_INTERFACE = 0x1;
+ final int LIBUSB_ENDPOINT_OUT = 0;
+
+ final int HID_SET_REPORT = 0x9;
+ final int HID_OUTPUT = (2 << 8);
+
+ int write = usb_con.controlTransfer(
+ LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
+ HID_SET_REPORT,
+ HID_OUTPUT | report_number,
+ index,
+ buf, size,
+ 1000);
+
+ if (write < 0)
+ return -1;
+
+ return write + 1;
+ }
+
+ public static boolean OpenAdapter()
+ {
+ // If the adapter is already open. Don't attempt to do it again
+ if (usb_con != null && usb_con.getFileDescriptor() != -1)
+ return true;
+
+ HashMap<String, UsbDevice> devices = manager.getDeviceList();
+ for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
+ {
+ UsbDevice dev = (UsbDevice) pair.getValue();
+ if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
+ {
+ if (manager.hasPermission(dev))
+ {
+ usb_con = manager.openDevice(dev);
+ UsbConfiguration conf = dev.getConfiguration(0);
+
+ Log.info("Number of configurations: " + dev.getConfigurationCount());
+ Log.info("Number of Interfaces: " + dev.getInterfaceCount());
+ Log.info("Number of Interfaces from conf: " + conf.getInterfaceCount());
+
+ // Sometimes the interface count is returned as zero.
+ // Means the device needs to be unplugged and plugged back in again
+ if (dev.getInterfaceCount() > 0)
+ {
+ for (int i = 0; i < MAX_WIIMOTES; ++i)
+ {
+ // One interface per Wiimote
+ usb_intf[i] = dev.getInterface(i);
+ usb_con.claimInterface(usb_intf[i], true);
+
+ // One endpoint per Wiimote. Input only
+ // Output reports go through the control channel.
+ usb_in[i] = usb_intf[i].getEndpoint(0);
+ Log.info("Interface " + i + " endpoint count:" + usb_intf[i].getEndpointCount());
+ }
+ return true;
+ }
+ else
+ {
+ // XXX: Message that the device was found, but it needs to be unplugged and plugged back in?
+ usb_con.close();
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml b/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
index 44093dc324..e218fac5b5 100644
--- a/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
+++ b/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
@@ -60,6 +60,11 @@
style="@style/InGameMenuOption"/>
<Button
+ android:id="@+id/menu_refresh_wiimotes"
+ android:text="@string/emulation_refresh_wiimotes"
+ style="@style/InGameMenuOption"/>
+
+ <Button
android:id="@+id/menu_exit"
android:text="@string/overlay_exit_emulation"
style="@style/InGameMenuOption"/>
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 4ae5e14c12..e3e309ca73 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -346,6 +346,7 @@
<string name="emulation_toggle_input">Toggle Touch Controls</string>
<string name="emulation_quicksave">Quick Save</string>
<string name="emulation_quickload">Quick Load</string>
+ <string name="emulation_refresh_wiimotes">Refresh Wiimotes</string>
<!-- GC Adapter Menu-->
<string name="gc_adapter_rumble">Enable Vibration</string>
diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp
index ffa0eca40a..7d2849c96e 100644
--- a/Source/Android/jni/MainAndroid.cpp
+++ b/Source/Android/jni/MainAndroid.cpp
@@ -27,6 +27,7 @@
#include "Core/Host.h"
#include "Core/State.h"
#include "Core/HW/Wiimote.h"
+#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/Profiler.h"
@@ -632,6 +633,10 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr
Renderer::s_ChangedSurface.Wait();
}
}
+JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv *env, jobject obj)
+{
+ WiimoteReal::Refresh();
+}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj)
{
@@ -646,6 +651,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
UICommon::SetUserDirectory(g_set_userpath);
UICommon::Init();
+ WiimoteReal::InitAdapterClass();
+
// No use running the loop when booting fails
if ( BootManager::BootCore( g_filename.c_str() ) )
{