Added support for claiming individiual interfaces on USB devices on Android
authorSam Lantinga <slouken@libsdl.org>
Mon, 13 Jan 2020 15:35:52 -0800
changeset 1341126cf14ba2193
parent 13410 e8651178fb1c
child 13412 4d575a1ef70a
Added support for claiming individiual interfaces on USB devices on Android
This is needed for supporting multiple wireless Xbox 360 controllers
android-project/app/src/main/java/org/libsdl/app/HIDDevice.java
android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java
android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java
android-project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java
     1.1 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDevice.java	Mon Jan 13 11:46:17 2020 -0500
     1.2 +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDevice.java	Mon Jan 13 15:35:52 2020 -0800
     1.3 @@ -1,5 +1,7 @@
     1.4  package org.libsdl.app;
     1.5  
     1.6 +import android.hardware.usb.UsbDevice;
     1.7 +
     1.8  interface HIDDevice
     1.9  {
    1.10      public int getId();
    1.11 @@ -9,6 +11,7 @@
    1.12      public int getVersion();
    1.13      public String getManufacturerName();
    1.14      public String getProductName();
    1.15 +    public UsbDevice getDevice();
    1.16      public boolean open();
    1.17      public int sendFeatureReport(byte[] report);
    1.18      public int sendOutputReport(byte[] report);
     2.1 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java	Mon Jan 13 11:46:17 2020 -0500
     2.2 +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java	Mon Jan 13 15:35:52 2020 -0800
     2.3 @@ -9,6 +9,7 @@
     2.4  import android.bluetooth.BluetoothManager;
     2.5  import android.bluetooth.BluetoothProfile;
     2.6  import android.bluetooth.BluetoothGattService;
     2.7 +import android.hardware.usb.UsbDevice;
     2.8  import android.os.Handler;
     2.9  import android.os.Looper;
    2.10  import android.util.Log;
    2.11 @@ -563,6 +564,11 @@
    2.12          return "Steam Controller";
    2.13      }
    2.14  
    2.15 +	@Override
    2.16 +    public UsbDevice getDevice() {
    2.17 +		return null;
    2.18 +	}
    2.19 +
    2.20      @Override
    2.21      public boolean open() {
    2.22          return true;
     3.1 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java	Mon Jan 13 11:46:17 2020 -0500
     3.2 +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java	Mon Jan 13 15:35:52 2020 -0800
     3.3 @@ -19,8 +19,9 @@
     3.4  import android.os.Handler;
     3.5  import android.os.Looper;
     3.6  
     3.7 +import java.util.ArrayList;
     3.8  import java.util.HashMap;
     3.9 -import java.util.ArrayList;
    3.10 +import java.util.Iterator;
    3.11  import java.util.List;
    3.12  
    3.13  public class HIDDeviceManager {
    3.14 @@ -50,7 +51,6 @@
    3.15  
    3.16      private Context mContext;
    3.17      private HashMap<Integer, HIDDevice> mDevicesById = new HashMap<Integer, HIDDevice>();
    3.18 -    private HashMap<UsbDevice, HIDDeviceUSB> mUSBDevices = new HashMap<UsbDevice, HIDDeviceUSB>();
    3.19      private HashMap<BluetoothDevice, HIDDeviceBLESteamController> mBluetoothDevices = new HashMap<BluetoothDevice, HIDDeviceBLESteamController>();
    3.20      private int mNextDeviceId = 0;
    3.21      private SharedPreferences mSharedPreferences = null;
    3.22 @@ -337,27 +337,30 @@
    3.23      }
    3.24  
    3.25      private void handleUsbDeviceDetached(UsbDevice usbDevice) {
    3.26 -        HIDDeviceUSB device = mUSBDevices.get(usbDevice);
    3.27 -        if (device == null)
    3.28 -            return;
    3.29 -
    3.30 -        int id = device.getId();
    3.31 -        mUSBDevices.remove(usbDevice);
    3.32 -        mDevicesById.remove(id);
    3.33 -        device.shutdown();
    3.34 -        HIDDeviceDisconnected(id);
    3.35 +        List<Integer> devices = new ArrayList<Integer>();
    3.36 +        for (HIDDevice device : mDevicesById.values()) {
    3.37 +            if (usbDevice.equals(device.getDevice())) {
    3.38 +                devices.add(device.getId());
    3.39 +            }
    3.40 +        }
    3.41 +        for (int id : devices) {
    3.42 +            HIDDevice device = mDevicesById.get(id);
    3.43 +            mDevicesById.remove(id);
    3.44 +            device.shutdown();
    3.45 +            HIDDeviceDisconnected(id);
    3.46 +        }
    3.47      }
    3.48  
    3.49      private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) {
    3.50 -        HIDDeviceUSB device = mUSBDevices.get(usbDevice);
    3.51 -        if (device == null)
    3.52 -            return;
    3.53 -
    3.54 -        boolean opened = false;
    3.55 -        if (permission_granted) {
    3.56 -            opened = device.open();
    3.57 +        for (HIDDevice device : mDevicesById.values()) {
    3.58 +            if (usbDevice.equals(device.getDevice())) {
    3.59 +                boolean opened = false;
    3.60 +                if (permission_granted) {
    3.61 +                    opened = device.open();
    3.62 +                }
    3.63 +                HIDDeviceOpenResult(device.getId(), opened);
    3.64 +            }
    3.65          }
    3.66 -        HIDDeviceOpenResult(device.getId(), opened);
    3.67      }
    3.68  
    3.69      private void connectHIDDeviceUSB(UsbDevice usbDevice) {
    3.70 @@ -366,10 +369,8 @@
    3.71                  if (isHIDDeviceInterface(usbDevice, interface_number)) {
    3.72                      HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_number);
    3.73                      int id = device.getId();
    3.74 -                    mUSBDevices.put(usbDevice, device);
    3.75                      mDevicesById.put(id, device);
    3.76                      HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), interface_number);
    3.77 -                    break;
    3.78                  }
    3.79              }
    3.80          }
    3.81 @@ -566,33 +567,27 @@
    3.82      //////////////////////////////////////////////////////////////////////////////////////////////////////
    3.83  
    3.84      public boolean openDevice(int deviceID) {
    3.85 +        Log.v(TAG, "openDevice deviceID=" + deviceID);
    3.86 +        HIDDevice device = getDevice(deviceID);
    3.87 +        if (device == null) {
    3.88 +            HIDDeviceDisconnected(deviceID);
    3.89 +            return false;
    3.90 +        }
    3.91 +
    3.92          // Look to see if this is a USB device and we have permission to access it
    3.93 -        for (HIDDeviceUSB device : mUSBDevices.values()) {
    3.94 -            if (deviceID == device.getId()) {
    3.95 -                UsbDevice usbDevice = device.getDevice();
    3.96 -                if (!mUsbManager.hasPermission(usbDevice)) {
    3.97 -                    HIDDeviceOpenPending(deviceID);
    3.98 -                    try {
    3.99 -                        mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0));
   3.100 -                    } catch (Exception e) {
   3.101 -                        Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
   3.102 -                        HIDDeviceOpenResult(deviceID, false);
   3.103 -                    }
   3.104 -                    return false;
   3.105 -                }
   3.106 -                break;
   3.107 +        UsbDevice usbDevice = device.getDevice();
   3.108 +        if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) {
   3.109 +            HIDDeviceOpenPending(deviceID);
   3.110 +            try {
   3.111 +                mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), 0));
   3.112 +            } catch (Exception e) {
   3.113 +                Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
   3.114 +                HIDDeviceOpenResult(deviceID, false);
   3.115              }
   3.116 +            return false;
   3.117          }
   3.118  
   3.119          try {
   3.120 -            Log.v(TAG, "openDevice deviceID=" + deviceID);
   3.121 -            HIDDevice device;
   3.122 -            device = getDevice(deviceID);
   3.123 -            if (device == null) {
   3.124 -                HIDDeviceDisconnected(deviceID);
   3.125 -                return false;
   3.126 -            }
   3.127 -
   3.128              return device.open();
   3.129          } catch (Exception e) {
   3.130              Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
   3.131 @@ -602,7 +597,7 @@
   3.132  
   3.133      public int sendOutputReport(int deviceID, byte[] report) {
   3.134          try {
   3.135 -            Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length);
   3.136 +            //Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length);
   3.137              HIDDevice device;
   3.138              device = getDevice(deviceID);
   3.139              if (device == null) {
   3.140 @@ -619,7 +614,7 @@
   3.141  
   3.142      public int sendFeatureReport(int deviceID, byte[] report) {
   3.143          try {
   3.144 -            Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length);
   3.145 +            //Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length);
   3.146              HIDDevice device;
   3.147              device = getDevice(deviceID);
   3.148              if (device == null) {
   3.149 @@ -636,7 +631,7 @@
   3.150  
   3.151      public boolean getFeatureReport(int deviceID, byte[] report) {
   3.152          try {
   3.153 -            Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
   3.154 +            //Log.v(TAG, "getFeatureReport deviceID=" + deviceID);
   3.155              HIDDevice device;
   3.156              device = getDevice(deviceID);
   3.157              if (device == null) {
     4.1 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java	Mon Jan 13 11:46:17 2020 -0500
     4.2 +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java	Mon Jan 13 15:35:52 2020 -0800
     4.3 @@ -29,7 +29,7 @@
     4.4      }
     4.5  
     4.6      public String getIdentifier() {
     4.7 -        return String.format("%s/%x/%x", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId());
     4.8 +        return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterface);
     4.9      }
    4.10  
    4.11      @Override
    4.12 @@ -88,6 +88,7 @@
    4.13          return result;
    4.14      }
    4.15  
    4.16 +	@Override
    4.17      public UsbDevice getDevice() {
    4.18          return mDevice;
    4.19      }
    4.20 @@ -104,19 +105,15 @@
    4.21              return false;
    4.22          }
    4.23  
    4.24 -        // Force claim all interfaces
    4.25 -        for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
    4.26 -            UsbInterface iface = mDevice.getInterface(i);
    4.27 -
    4.28 -            if (!mConnection.claimInterface(iface, true)) {
    4.29 -                Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName());
    4.30 -                close();
    4.31 -                return false;
    4.32 -            }
    4.33 +        // Force claim our interface
    4.34 +        UsbInterface iface = mDevice.getInterface(mInterface);
    4.35 +        if (!mConnection.claimInterface(iface, true)) {
    4.36 +            Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName());
    4.37 +            close();
    4.38 +            return false;
    4.39          }
    4.40  
    4.41          // Find the endpoints
    4.42 -        UsbInterface iface = mDevice.getInterface(mInterface);
    4.43          for (int j = 0; j < iface.getEndpointCount(); j++) {
    4.44              UsbEndpoint endpt = iface.getEndpoint(j);
    4.45              switch (endpt.getDirection()) {
    4.46 @@ -250,10 +247,8 @@
    4.47              mInputThread = null;
    4.48          }
    4.49          if (mConnection != null) {
    4.50 -            for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
    4.51 -                UsbInterface iface = mDevice.getInterface(i);
    4.52 -                mConnection.releaseInterface(iface);
    4.53 -            }
    4.54 +            UsbInterface iface = mDevice.getInterface(mInterface);
    4.55 +            mConnection.releaseInterface(iface);
    4.56              mConnection.close();
    4.57              mConnection = null;
    4.58          }