diff options
Diffstat (limited to 'Source/Android/app/src/main/java')
| -rw-r--r-- | Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java | 8 | ||||
| -rw-r--r-- | Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GCAdapter.java | 259 | ||||
| -rw-r--r-- | Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java | 158 | ||||
| -rw-r--r-- | Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiimoteAdapter.java (renamed from Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java) | 40 |
4 files changed, 283 insertions, 182 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java index 8ff78ebb0e..91200852a1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java @@ -9,8 +9,8 @@ import android.hardware.usb.UsbManager; import org.dolphinemu.dolphinemu.utils.ActivityTracker; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; -import org.dolphinemu.dolphinemu.utils.Java_GCAdapter; -import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter; +import org.dolphinemu.dolphinemu.utils.GCAdapter; +import org.dolphinemu.dolphinemu.utils.WiimoteAdapter; import org.dolphinemu.dolphinemu.utils.VolleyUtil; public class DolphinApplication extends Application @@ -28,8 +28,8 @@ public class DolphinApplication extends Application VolleyUtil.init(getApplicationContext()); System.loadLibrary("main"); - Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); - Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); + GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); + WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); if (DirectoryInitialization.shouldStart(getApplicationContext())) DirectoryInitialization.start(getApplicationContext()); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GCAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GCAdapter.java new file mode 100644 index 0000000000..b9e67e654f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GCAdapter.java @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.utils; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbConfiguration; +import android.hardware.usb.UsbConstants; +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 android.os.Build; +import android.widget.Toast; + +import androidx.annotation.Keep; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.DolphinApplication; +import org.dolphinemu.dolphinemu.R; + +import java.util.HashMap; +import java.util.Map; + +public class GCAdapter +{ + public static UsbManager manager; + + @Keep + static byte[] controllerPayload = new byte[37]; + + static UsbDeviceConnection usbConnection; + static UsbInterface usbInterface; + static UsbEndpoint usbIn; + static UsbEndpoint usbOut; + + private static final String ACTION_GC_ADAPTER_PERMISSION_GRANTED = + BuildConfig.APPLICATION_ID + ".GC_ADAPTER_PERMISSION_GRANTED"; + + private static final Object hotplugCallbackLock = new Object(); + private static boolean hotplugCallbackEnabled = false; + private static UsbDevice adapterDevice = null; + private static BroadcastReceiver hotplugBroadcastReceiver = new BroadcastReceiver() + { + @Override + public void onReceive(Context context, Intent intent) + { + onUsbDevicesChanged(); + } + }; + + private static void requestPermission() + { + HashMap<String, UsbDevice> devices = manager.getDeviceList(); + for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) + { + UsbDevice dev = pair.getValue(); + if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) + { + if (!manager.hasPermission(dev)) + { + Context context = DolphinApplication.getAppContext(); + + int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? + PendingIntent.FLAG_IMMUTABLE : 0; + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, + new Intent(ACTION_GC_ADAPTER_PERMISSION_GRANTED), flags); + + manager.requestPermission(dev, pendingIntent); + } + } + } + } + + public static void shutdown() + { + usbConnection.close(); + } + + @Keep + public static int getFd() + { + return usbConnection.getFileDescriptor(); + } + + @Keep + public static boolean isUsbDeviceAvailable() + { + synchronized (hotplugCallbackLock) + { + return adapterDevice != null; + } + } + + @Nullable + private static UsbDevice queryAdapter() + { + HashMap<String, UsbDevice> devices = manager.getDeviceList(); + for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) + { + UsbDevice dev = pair.getValue(); + if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) + { + if (manager.hasPermission(dev)) + return dev; + else + requestPermission(); + } + } + return null; + } + + public static void initAdapter() + { + byte[] init = {0x13}; + usbConnection.bulkTransfer(usbOut, init, init.length, 0); + } + + @Keep + public static int input() + { + return usbConnection.bulkTransfer(usbIn, controllerPayload, controllerPayload.length, 16); + } + + @Keep + public static int output(byte[] rumble) + { + return usbConnection.bulkTransfer(usbOut, rumble, 5, 16); + } + + @Keep + public static boolean openAdapter() + { + UsbDevice dev; + synchronized (hotplugCallbackLock) + { + dev = adapterDevice; + } + if (dev == null) + { + return false; + } + + usbConnection = manager.openDevice(dev); + if (usbConnection == null) + { + return false; + } + + Log.info("GCAdapter: Number of configurations: " + dev.getConfigurationCount()); + Log.info("GCAdapter: Number of interfaces: " + dev.getInterfaceCount()); + + if (dev.getConfigurationCount() > 0 && dev.getInterfaceCount() > 0) + { + UsbConfiguration conf = dev.getConfiguration(0); + usbInterface = conf.getInterface(0); + usbConnection.claimInterface(usbInterface, true); + + Log.info("GCAdapter: Number of endpoints: " + usbInterface.getEndpointCount()); + + if (usbInterface.getEndpointCount() == 2) + { + for (int i = 0; i < usbInterface.getEndpointCount(); ++i) + if (usbInterface.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) + usbIn = usbInterface.getEndpoint(i); + else + usbOut = usbInterface.getEndpoint(i); + + initAdapter(); + return true; + } + else + { + usbConnection.releaseInterface(usbInterface); + } + } + + Toast.makeText(DolphinApplication.getAppContext(), R.string.replug_gc_adapter, + Toast.LENGTH_LONG).show(); + usbConnection.close(); + return false; + } + + @Keep + public static void enableHotplugCallback() + { + synchronized (hotplugCallbackLock) + { + if (hotplugCallbackEnabled) + { + throw new IllegalStateException("enableHotplugCallback was called when already enabled"); + } + + IntentFilter filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); + filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); + filter.addAction(ACTION_GC_ADAPTER_PERMISSION_GRANTED); + + ContextCompat.registerReceiver(DolphinApplication.getAppContext(), hotplugBroadcastReceiver, + filter, ContextCompat.RECEIVER_EXPORTED); + + hotplugCallbackEnabled = true; + + onUsbDevicesChanged(); + } + } + + @Keep + public static void disableHotplugCallback() + { + synchronized (hotplugCallbackLock) + { + if (hotplugCallbackEnabled) + { + DolphinApplication.getAppContext().unregisterReceiver(hotplugBroadcastReceiver); + hotplugCallbackEnabled = false; + adapterDevice = null; + } + } + } + + public static void onUsbDevicesChanged() + { + synchronized (hotplugCallbackLock) + { + if (adapterDevice != null) + { + boolean adapterStillConnected = manager.getDeviceList().entrySet().stream() + .anyMatch(pair -> pair.getValue().getDeviceId() == adapterDevice.getDeviceId()); + + if (!adapterStillConnected) + { + adapterDevice = null; + onAdapterDisconnected(); + } + } + + if (adapterDevice == null) + { + UsbDevice newAdapter = queryAdapter(); + if (newAdapter != null) + { + adapterDevice = newAdapter; + onAdapterConnected(); + } + } + } + } + + private static native void onAdapterConnected(); + + private static native void onAdapterDisconnected(); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java deleted file mode 100644 index 3fcd58afac..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.utils; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.hardware.usb.UsbConfiguration; -import android.hardware.usb.UsbConstants; -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 android.os.Build; -import android.widget.Toast; - -import androidx.annotation.Keep; - -import org.dolphinemu.dolphinemu.DolphinApplication; -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.services.USBPermService; - -import java.util.HashMap; -import java.util.Map; - -public class Java_GCAdapter -{ - public static UsbManager manager; - - @Keep - static byte[] controller_payload = new byte[37]; - - static UsbDeviceConnection usb_con; - static UsbInterface usb_intf; - static UsbEndpoint usb_in; - static UsbEndpoint usb_out; - - private static void RequestPermission() - { - HashMap<String, UsbDevice> devices = manager.getDeviceList(); - for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) - { - UsbDevice dev = pair.getValue(); - if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) - { - if (!manager.hasPermission(dev)) - { - Context context = DolphinApplication.getAppContext(); - Intent intent = new Intent(context, USBPermService.class); - - int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? - PendingIntent.FLAG_IMMUTABLE : 0; - PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, flags); - - manager.requestPermission(dev, pendingIntent); - } - } - } - } - - public static void Shutdown() - { - usb_con.close(); - } - - @Keep - public static int GetFD() - { - return usb_con.getFileDescriptor(); - } - - @Keep - public static boolean QueryAdapter() - { - HashMap<String, UsbDevice> devices = manager.getDeviceList(); - for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) - { - UsbDevice dev = pair.getValue(); - if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) - { - if (manager.hasPermission(dev)) - return true; - else - RequestPermission(); - } - } - return false; - } - - public static void InitAdapter() - { - byte[] init = {0x13}; - usb_con.bulkTransfer(usb_out, init, init.length, 0); - } - - @Keep - public static int Input() - { - return usb_con.bulkTransfer(usb_in, controller_payload, controller_payload.length, 16); - } - - @Keep - public static int Output(byte[] rumble) - { - return usb_con.bulkTransfer(usb_out, rumble, 5, 16); - } - - @Keep - public static boolean OpenAdapter() - { - HashMap<String, UsbDevice> devices = manager.getDeviceList(); - for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) - { - UsbDevice dev = pair.getValue(); - if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) - { - if (manager.hasPermission(dev)) - { - usb_con = manager.openDevice(dev); - - Log.info("GCAdapter: Number of configurations: " + dev.getConfigurationCount()); - Log.info("GCAdapter: Number of interfaces: " + dev.getInterfaceCount()); - - if (dev.getConfigurationCount() > 0 && dev.getInterfaceCount() > 0) - { - UsbConfiguration conf = dev.getConfiguration(0); - usb_intf = conf.getInterface(0); - usb_con.claimInterface(usb_intf, true); - - Log.info("GCAdapter: Number of endpoints: " + usb_intf.getEndpointCount()); - - if (usb_intf.getEndpointCount() == 2) - { - for (int i = 0; i < usb_intf.getEndpointCount(); ++i) - if (usb_intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) - usb_in = usb_intf.getEndpoint(i); - else - usb_out = usb_intf.getEndpoint(i); - - InitAdapter(); - return true; - } - else - { - usb_con.releaseInterface(usb_intf); - } - } - - Toast.makeText(DolphinApplication.getAppContext(), R.string.replug_gc_adapter, - Toast.LENGTH_LONG).show(); - usb_con.close(); - } - } - } - return false; - } -} 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/WiimoteAdapter.java index 469375614f..98a7d51900 100644 --- 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/WiimoteAdapter.java @@ -22,7 +22,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -public class Java_WiimoteAdapter +public class WiimoteAdapter { final static int MAX_PAYLOAD = 23; final static int MAX_WIIMOTES = 4; @@ -31,14 +31,14 @@ public class Java_WiimoteAdapter 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]; + static UsbDeviceConnection usbConnection; + static UsbInterface[] usbInterface = new UsbInterface[MAX_WIIMOTES]; + static UsbEndpoint[] usbIn = new UsbEndpoint[MAX_WIIMOTES]; @Keep - public static byte[][] wiimote_payload = new byte[MAX_WIIMOTES][MAX_PAYLOAD]; + public static byte[][] wiimotePayload = new byte[MAX_WIIMOTES][MAX_PAYLOAD]; - private static void RequestPermission() + private static void requestPermission() { HashMap<String, UsbDevice> devices = manager.getDeviceList(); for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) @@ -65,7 +65,7 @@ public class Java_WiimoteAdapter } @Keep - public static boolean QueryAdapter() + public static boolean queryAdapter() { HashMap<String, UsbDevice> devices = manager.getDeviceList(); for (Map.Entry<String, UsbDevice> pair : devices.entrySet()) @@ -77,20 +77,20 @@ public class Java_WiimoteAdapter if (manager.hasPermission(dev)) return true; else - RequestPermission(); + requestPermission(); } } return false; } @Keep - public static int Input(int index) + public static int input(int index) { - return usb_con.bulkTransfer(usb_in[index], wiimote_payload[index], MAX_PAYLOAD, TIMEOUT); + return usbConnection.bulkTransfer(usbIn[index], wiimotePayload[index], MAX_PAYLOAD, TIMEOUT); } @Keep - public static int Output(int index, byte[] buf, int size) + public static int output(int index, byte[] buf, int size) { byte report_number = buf[0]; @@ -105,7 +105,7 @@ public class Java_WiimoteAdapter final int HID_SET_REPORT = 0x9; final int HID_OUTPUT = (2 << 8); - int write = usb_con.controlTransfer( + int write = usbConnection.controlTransfer( LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, HID_SET_REPORT, HID_OUTPUT | report_number, @@ -120,10 +120,10 @@ public class Java_WiimoteAdapter } @Keep - public static boolean OpenAdapter() + 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) + if (usbConnection != null && usbConnection.getFileDescriptor() != -1) return true; HashMap<String, UsbDevice> devices = manager.getDeviceList(); @@ -135,7 +135,7 @@ public class Java_WiimoteAdapter { if (manager.hasPermission(dev)) { - usb_con = manager.openDevice(dev); + usbConnection = manager.openDevice(dev); UsbConfiguration conf = dev.getConfiguration(0); Log.info("Number of configurations: " + dev.getConfigurationCount()); @@ -149,20 +149,20 @@ public class Java_WiimoteAdapter for (int i = 0; i < MAX_WIIMOTES; ++i) { // One interface per Wii Remote - usb_intf[i] = dev.getInterface(i); - usb_con.claimInterface(usb_intf[i], true); + usbInterface[i] = dev.getInterface(i); + usbConnection.claimInterface(usbInterface[i], true); // One endpoint per Wii Remote. 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()); + usbIn[i] = usbInterface[i].getEndpoint(0); + Log.info("Interface " + i + " endpoint count:" + usbInterface[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(); + usbConnection.close(); } } } |
