kivyforge 3.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kivyforge/__init__.py +9 -0
- kivyforge/artifacts/__init__.py +41 -0
- kivyforge/artifacts/cache.py +81 -0
- kivyforge/artifacts/collect.py +354 -0
- kivyforge/artifacts/download.py +125 -0
- kivyforge/artifacts/frameworks.py +240 -0
- kivyforge/artifacts/native_stage_util.py +346 -0
- kivyforge/artifacts/runtime.py +65 -0
- kivyforge/artifacts/verify.py +45 -0
- kivyforge/artifacts/wheels.py +89 -0
- kivyforge/bundle/__init__.py +1 -0
- kivyforge/bundle/pycompile.py +161 -0
- kivyforge/cli/__init__.py +52 -0
- kivyforge/cli/_common.py +62 -0
- kivyforge/cli/_platform.py +84 -0
- kivyforge/cli/build.py +111 -0
- kivyforge/cli/clean.py +135 -0
- kivyforge/cli/doctor.py +52 -0
- kivyforge/cli/init.py +612 -0
- kivyforge/cli/init_writer.py +716 -0
- kivyforge/cli/lock.py +261 -0
- kivyforge/cli/open_cmd.py +15 -0
- kivyforge/cli/package.py +134 -0
- kivyforge/cli/run.py +162 -0
- kivyforge/cli/status.py +20 -0
- kivyforge/cli/upgrade.py +314 -0
- kivyforge/config/__init__.py +46 -0
- kivyforge/config/errors.py +43 -0
- kivyforge/config/icons.py +60 -0
- kivyforge/config/loader.py +3079 -0
- kivyforge/config/model.py +817 -0
- kivyforge/doctor/__init__.py +19 -0
- kivyforge/doctor/checks_common.py +95 -0
- kivyforge/doctor/probe.py +357 -0
- kivyforge/doctor/result.py +41 -0
- kivyforge/lock/__init__.py +42 -0
- kivyforge/lock/_pip_shim.py +63 -0
- kivyforge/lock/find_links.py +182 -0
- kivyforge/lock/model.py +69 -0
- kivyforge/lock/pep751.py +111 -0
- kivyforge/lock/reader.py +30 -0
- kivyforge/lock/resolver.py +124 -0
- kivyforge/lock/wheelruntime/__init__.py +70 -0
- kivyforge/lock/wheelruntime/builder.py +280 -0
- kivyforge/lock/wheelruntime/model.py +94 -0
- kivyforge/lock/wheelruntime/native_binaries.py +127 -0
- kivyforge/lock/wheelruntime/pbs_github.py +133 -0
- kivyforge/lock/wheelruntime/profile.py +104 -0
- kivyforge/lock/wheelruntime/resolver.py +248 -0
- kivyforge/lock/wheelruntime/runtime.py +161 -0
- kivyforge/lock/wheelruntime/serialize.py +245 -0
- kivyforge/platforms/__init__.py +114 -0
- kivyforge/platforms/android/__init__.py +140 -0
- kivyforge/platforms/android/adb.py +215 -0
- kivyforge/platforms/android/bootstrap/__init__.py +7 -0
- kivyforge/platforms/android/bootstrap/contract.py +166 -0
- kivyforge/platforms/android/bootstrap/render.py +244 -0
- kivyforge/platforms/android/bootstrap/templates/androidtest/KivyforgeContractTest.java +76 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivy_bootstrap.py +50 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_bootstrap.py +54 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_selftest.py +97 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/CMakeLists.txt +20 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/main.c +150 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/jnius/NativeInvocationHandler.java +48 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonActivity.java +75 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonBundle.java +132 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonService.java +189 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/renpy/android/Hardware.java +276 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDevice.java +22 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceBLESteamController.java +650 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceUSB.java +309 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLActivity.java +2120 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLAudioManager.java +514 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLControllerManager.java +856 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLSurface.java +405 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDevice.java +21 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceBLESteamController.java +829 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceUSB.java +354 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLActivity.java +2240 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLAudioManager.java +126 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLControllerManager.java +1010 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLDummyEdit.java +66 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLInputConnection.java +136 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSensorManager.java +73 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSurface.java +464 -0
- kivyforge/platforms/android/cli.py +1023 -0
- kivyforge/platforms/android/doctor.py +899 -0
- kivyforge/platforms/android/elf.py +148 -0
- kivyforge/platforms/android/generate/__init__.py +1 -0
- kivyforge/platforms/android/generate/manifest.py +261 -0
- kivyforge/platforms/android/generate/project.py +462 -0
- kivyforge/platforms/android/generate/services.py +187 -0
- kivyforge/platforms/android/gradle_wrapper/NOTICE +3 -0
- kivyforge/platforms/android/gradle_wrapper/SHA256SUMS +1 -0
- kivyforge/platforms/android/gradle_wrapper/gradle-wrapper.jar +0 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew +164 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew.bat +90 -0
- kivyforge/platforms/android/gradlew.py +60 -0
- kivyforge/platforms/android/icons.py +237 -0
- kivyforge/platforms/android/lock/__init__.py +1 -0
- kivyforge/platforms/android/lock/archives.py +109 -0
- kivyforge/platforms/android/lock/builder.py +387 -0
- kivyforge/platforms/android/lock/markers.py +71 -0
- kivyforge/platforms/android/lock/maven.py +252 -0
- kivyforge/platforms/android/lock/model.py +113 -0
- kivyforge/platforms/android/lock/python_meta.py +199 -0
- kivyforge/platforms/android/lock/reader.py +206 -0
- kivyforge/platforms/android/lock/resolver.py +276 -0
- kivyforge/platforms/android/lock/writer.py +121 -0
- kivyforge/platforms/android/policy.py +214 -0
- kivyforge/platforms/android/signing.py +145 -0
- kivyforge/platforms/android/smoke.py +43 -0
- kivyforge/platforms/android/splash.py +293 -0
- kivyforge/platforms/android/stage/__init__.py +1 -0
- kivyforge/platforms/android/stage/bundle.py +295 -0
- kivyforge/platforms/android/stage/jnilibs.py +186 -0
- kivyforge/platforms/android/stage/runtime.py +61 -0
- kivyforge/platforms/android/stage/wheels.py +106 -0
- kivyforge/platforms/android/toolchain.py +29 -0
- kivyforge/platforms/base.py +157 -0
- kivyforge/platforms/ios/__init__.py +129 -0
- kivyforge/platforms/ios/assets.py +193 -0
- kivyforge/platforms/ios/buildsettings.py +128 -0
- kivyforge/platforms/ios/cli.py +543 -0
- kivyforge/platforms/ios/doctor.py +410 -0
- kivyforge/platforms/ios/entitlements.py +34 -0
- kivyforge/platforms/ios/generator.py +318 -0
- kivyforge/platforms/ios/lock/__init__.py +71 -0
- kivyforge/platforms/ios/lock/builder.py +393 -0
- kivyforge/platforms/ios/lock/markers.py +69 -0
- kivyforge/platforms/ios/lock/model.py +95 -0
- kivyforge/platforms/ios/lock/python_meta.py +187 -0
- kivyforge/platforms/ios/lock/reader.py +191 -0
- kivyforge/platforms/ios/lock/resolver.py +304 -0
- kivyforge/platforms/ios/lock/spm.py +217 -0
- kivyforge/platforms/ios/lock/writer.py +114 -0
- kivyforge/platforms/ios/lock/xcframework.py +188 -0
- kivyforge/platforms/ios/materialize.py +59 -0
- kivyforge/platforms/ios/plist.py +91 -0
- kivyforge/platforms/ios/privacy.py +39 -0
- kivyforge/platforms/ios/skeleton.py +165 -0
- kivyforge/platforms/ios/sources.py +63 -0
- kivyforge/platforms/ios/staging.py +225 -0
- kivyforge/platforms/ios/swift_packages.py +324 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.h +34 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.m +146 -0
- kivyforge/platforms/ios/templates/main.m +15 -0
- kivyforge/platforms/ios/templates/main_config.h.in +12 -0
- kivyforge/platforms/ios/xcframeworks.py +194 -0
- kivyforge/platforms/ios/xcode/__init__.py +76 -0
- kivyforge/platforms/ios/xcode/commands.py +296 -0
- kivyforge/platforms/ios/xcode/runner.py +316 -0
- kivyforge/platforms/linux/__init__.py +120 -0
- kivyforge/platforms/linux/appimage.py +169 -0
- kivyforge/platforms/linux/bundle.py +235 -0
- kivyforge/platforms/linux/cli.py +232 -0
- kivyforge/platforms/linux/desktop.py +71 -0
- kivyforge/platforms/linux/doctor.py +438 -0
- kivyforge/platforms/linux/elftools.py +95 -0
- kivyforge/platforms/linux/icons.py +129 -0
- kivyforge/platforms/linux/launcher.py +107 -0
- kivyforge/platforms/linux/lock/__init__.py +126 -0
- kivyforge/platforms/linux/lock/profile.py +254 -0
- kivyforge/platforms/linux/lock/runtime.py +75 -0
- kivyforge/platforms/linux/native_stage.py +47 -0
- kivyforge/platforms/linux/runtime_stage.py +107 -0
- kivyforge/platforms/linux/wheels_stage.py +103 -0
- kivyforge/platforms/macos/__init__.py +121 -0
- kivyforge/platforms/macos/bundle.py +255 -0
- kivyforge/platforms/macos/cli.py +269 -0
- kivyforge/platforms/macos/doctor.py +480 -0
- kivyforge/platforms/macos/icns.py +75 -0
- kivyforge/platforms/macos/launcher.py +118 -0
- kivyforge/platforms/macos/lock/__init__.py +112 -0
- kivyforge/platforms/macos/lock/profile.py +119 -0
- kivyforge/platforms/macos/lock/runtime.py +58 -0
- kivyforge/platforms/macos/machotools.py +138 -0
- kivyforge/platforms/macos/native_stage.py +47 -0
- kivyforge/platforms/macos/notarize.py +143 -0
- kivyforge/platforms/macos/plist.py +37 -0
- kivyforge/platforms/macos/runtime_stage.py +110 -0
- kivyforge/platforms/macos/signing.py +78 -0
- kivyforge/platforms/macos/wheels_stage.py +108 -0
- kivyforge/platforms/windows/__init__.py +133 -0
- kivyforge/platforms/windows/assets.py +76 -0
- kivyforge/platforms/windows/bundle.py +298 -0
- kivyforge/platforms/windows/cli.py +314 -0
- kivyforge/platforms/windows/doctor.py +563 -0
- kivyforge/platforms/windows/fsswap.py +87 -0
- kivyforge/platforms/windows/icons.py +64 -0
- kivyforge/platforms/windows/launcher/__init__.py +193 -0
- kivyforge/platforms/windows/launcher/build_launcher.py +507 -0
- kivyforge/platforms/windows/launcher/launcher.c +379 -0
- kivyforge/platforms/windows/lock/__init__.py +112 -0
- kivyforge/platforms/windows/lock/profile.py +101 -0
- kivyforge/platforms/windows/lock/runtime.py +64 -0
- kivyforge/platforms/windows/naming.py +52 -0
- kivyforge/platforms/windows/native_stage.py +66 -0
- kivyforge/platforms/windows/petools.py +98 -0
- kivyforge/platforms/windows/rcedit.py +116 -0
- kivyforge/platforms/windows/runtime_stage.py +221 -0
- kivyforge/platforms/windows/signing.py +168 -0
- kivyforge/platforms/windows/vendor/LICENSE.rcedit +29 -0
- kivyforge/platforms/windows/vendor/NOTICE +17 -0
- kivyforge/platforms/windows/vendor/SHA256SUMS +4 -0
- kivyforge/platforms/windows/vendor/TOOLSET.txt +4 -0
- kivyforge/platforms/windows/vendor/__init__.py +12 -0
- kivyforge/platforms/windows/vendor/fetch_rcedit.py +97 -0
- kivyforge/platforms/windows/vendor/launcher-amd64.exe +0 -0
- kivyforge/platforms/windows/vendor/rcedit-x64.exe +0 -0
- kivyforge/platforms/windows/wheels_stage.py +139 -0
- kivyforge-3.0.0.dev0.dist-info/METADATA +609 -0
- kivyforge-3.0.0.dev0.dist-info/RECORD +225 -0
- kivyforge-3.0.0.dev0.dist-info/WHEEL +5 -0
- kivyforge-3.0.0.dev0.dist-info/entry_points.txt +3 -0
- kivyforge-3.0.0.dev0.dist-info/licenses/LICENSE +21 -0
- kivyforge-3.0.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
package org.libsdl.app;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.app.AlertDialog;
|
|
5
|
+
import android.app.PendingIntent;
|
|
6
|
+
import android.bluetooth.BluetoothAdapter;
|
|
7
|
+
import android.bluetooth.BluetoothDevice;
|
|
8
|
+
import android.bluetooth.BluetoothManager;
|
|
9
|
+
import android.bluetooth.BluetoothProfile;
|
|
10
|
+
import android.os.Build;
|
|
11
|
+
import android.util.Log;
|
|
12
|
+
import android.content.BroadcastReceiver;
|
|
13
|
+
import android.content.Context;
|
|
14
|
+
import android.content.DialogInterface;
|
|
15
|
+
import android.content.Intent;
|
|
16
|
+
import android.content.IntentFilter;
|
|
17
|
+
import android.content.SharedPreferences;
|
|
18
|
+
import android.content.pm.PackageManager;
|
|
19
|
+
import android.hardware.usb.*;
|
|
20
|
+
import android.os.Handler;
|
|
21
|
+
import android.os.Looper;
|
|
22
|
+
|
|
23
|
+
import java.util.ArrayList;
|
|
24
|
+
import java.util.HashMap;
|
|
25
|
+
import java.util.Iterator;
|
|
26
|
+
import java.util.List;
|
|
27
|
+
|
|
28
|
+
public class HIDDeviceManager {
|
|
29
|
+
private static final String TAG = "hidapi";
|
|
30
|
+
private static final String ACTION_USB_PERMISSION = "org.libsdl.app.USB_PERMISSION";
|
|
31
|
+
|
|
32
|
+
private static HIDDeviceManager sManager;
|
|
33
|
+
private static int sManagerRefCount = 0;
|
|
34
|
+
|
|
35
|
+
static public HIDDeviceManager acquire(Context context) {
|
|
36
|
+
if (sManagerRefCount == 0) {
|
|
37
|
+
sManager = new HIDDeviceManager(context);
|
|
38
|
+
}
|
|
39
|
+
++sManagerRefCount;
|
|
40
|
+
return sManager;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static public void release(HIDDeviceManager manager) {
|
|
44
|
+
if (manager == sManager) {
|
|
45
|
+
--sManagerRefCount;
|
|
46
|
+
if (sManagerRefCount == 0) {
|
|
47
|
+
sManager.close();
|
|
48
|
+
sManager = null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private Context mContext;
|
|
54
|
+
private HashMap<Integer, HIDDevice> mDevicesById = new HashMap<Integer, HIDDevice>();
|
|
55
|
+
private HashMap<BluetoothDevice, HIDDeviceBLESteamController> mBluetoothDevices = new HashMap<BluetoothDevice, HIDDeviceBLESteamController>();
|
|
56
|
+
private int mNextDeviceId = 0;
|
|
57
|
+
private SharedPreferences mSharedPreferences = null;
|
|
58
|
+
private boolean mIsChromebook = false;
|
|
59
|
+
private UsbManager mUsbManager;
|
|
60
|
+
private Handler mHandler;
|
|
61
|
+
private BluetoothManager mBluetoothManager;
|
|
62
|
+
private List<BluetoothDevice> mLastBluetoothDevices;
|
|
63
|
+
|
|
64
|
+
private final BroadcastReceiver mUsbBroadcast = new BroadcastReceiver() {
|
|
65
|
+
@Override
|
|
66
|
+
public void onReceive(Context context, Intent intent) {
|
|
67
|
+
String action = intent.getAction();
|
|
68
|
+
if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
|
|
69
|
+
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
70
|
+
handleUsbDeviceAttached(usbDevice);
|
|
71
|
+
} else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
|
|
72
|
+
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
73
|
+
handleUsbDeviceDetached(usbDevice);
|
|
74
|
+
} else if (action.equals(HIDDeviceManager.ACTION_USB_PERMISSION)) {
|
|
75
|
+
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
|
76
|
+
handleUsbDevicePermission(usbDevice, intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
private final BroadcastReceiver mBluetoothBroadcast = new BroadcastReceiver() {
|
|
82
|
+
@Override
|
|
83
|
+
public void onReceive(Context context, Intent intent) {
|
|
84
|
+
String action = intent.getAction();
|
|
85
|
+
// Bluetooth device was connected. If it was a Steam Controller, handle it
|
|
86
|
+
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
|
|
87
|
+
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
88
|
+
Log.d(TAG, "Bluetooth device connected: " + device);
|
|
89
|
+
|
|
90
|
+
if (isSteamController(device)) {
|
|
91
|
+
connectBluetoothDevice(device);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Bluetooth device was disconnected, remove from controller manager (if any)
|
|
96
|
+
if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
|
|
97
|
+
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
|
98
|
+
Log.d(TAG, "Bluetooth device disconnected: " + device);
|
|
99
|
+
|
|
100
|
+
disconnectBluetoothDevice(device);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
private HIDDeviceManager(final Context context) {
|
|
106
|
+
mContext = context;
|
|
107
|
+
|
|
108
|
+
HIDDeviceRegisterCallback();
|
|
109
|
+
|
|
110
|
+
mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE);
|
|
111
|
+
mIsChromebook = SDLActivity.isChromebook();
|
|
112
|
+
|
|
113
|
+
// if (shouldClear) {
|
|
114
|
+
// SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
|
115
|
+
// spedit.clear();
|
|
116
|
+
// spedit.apply();
|
|
117
|
+
// }
|
|
118
|
+
// else
|
|
119
|
+
{
|
|
120
|
+
mNextDeviceId = mSharedPreferences.getInt("next_device_id", 0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Context getContext() {
|
|
125
|
+
return mContext;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
int getDeviceIDForIdentifier(String identifier) {
|
|
129
|
+
SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
|
130
|
+
|
|
131
|
+
int result = mSharedPreferences.getInt(identifier, 0);
|
|
132
|
+
if (result == 0) {
|
|
133
|
+
result = mNextDeviceId++;
|
|
134
|
+
spedit.putInt("next_device_id", mNextDeviceId);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
spedit.putInt(identifier, result);
|
|
138
|
+
spedit.apply();
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private void initializeUSB() {
|
|
143
|
+
mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
|
|
144
|
+
if (mUsbManager == null) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
// Logging
|
|
150
|
+
for (UsbDevice device : mUsbManager.getDeviceList().values()) {
|
|
151
|
+
Log.i(TAG,"Path: " + device.getDeviceName());
|
|
152
|
+
Log.i(TAG,"Manufacturer: " + device.getManufacturerName());
|
|
153
|
+
Log.i(TAG,"Product: " + device.getProductName());
|
|
154
|
+
Log.i(TAG,"ID: " + device.getDeviceId());
|
|
155
|
+
Log.i(TAG,"Class: " + device.getDeviceClass());
|
|
156
|
+
Log.i(TAG,"Protocol: " + device.getDeviceProtocol());
|
|
157
|
+
Log.i(TAG,"Vendor ID " + device.getVendorId());
|
|
158
|
+
Log.i(TAG,"Product ID: " + device.getProductId());
|
|
159
|
+
Log.i(TAG,"Interface count: " + device.getInterfaceCount());
|
|
160
|
+
Log.i(TAG,"---------------------------------------");
|
|
161
|
+
|
|
162
|
+
// Get interface details
|
|
163
|
+
for (int index = 0; index < device.getInterfaceCount(); index++) {
|
|
164
|
+
UsbInterface mUsbInterface = device.getInterface(index);
|
|
165
|
+
Log.i(TAG," ***** *****");
|
|
166
|
+
Log.i(TAG," Interface index: " + index);
|
|
167
|
+
Log.i(TAG," Interface ID: " + mUsbInterface.getId());
|
|
168
|
+
Log.i(TAG," Interface class: " + mUsbInterface.getInterfaceClass());
|
|
169
|
+
Log.i(TAG," Interface subclass: " + mUsbInterface.getInterfaceSubclass());
|
|
170
|
+
Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol());
|
|
171
|
+
Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount());
|
|
172
|
+
|
|
173
|
+
// Get endpoint details
|
|
174
|
+
for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++)
|
|
175
|
+
{
|
|
176
|
+
UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi);
|
|
177
|
+
Log.i(TAG," ++++ ++++ ++++");
|
|
178
|
+
Log.i(TAG," Endpoint index: " + epi);
|
|
179
|
+
Log.i(TAG," Attributes: " + mEndpoint.getAttributes());
|
|
180
|
+
Log.i(TAG," Direction: " + mEndpoint.getDirection());
|
|
181
|
+
Log.i(TAG," Number: " + mEndpoint.getEndpointNumber());
|
|
182
|
+
Log.i(TAG," Interval: " + mEndpoint.getInterval());
|
|
183
|
+
Log.i(TAG," Packet size: " + mEndpoint.getMaxPacketSize());
|
|
184
|
+
Log.i(TAG," Type: " + mEndpoint.getType());
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
Log.i(TAG," No more devices connected.");
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
// Register for USB broadcasts and permission completions
|
|
192
|
+
IntentFilter filter = new IntentFilter();
|
|
193
|
+
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
|
194
|
+
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
|
|
195
|
+
filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);
|
|
196
|
+
if (Build.VERSION.SDK_INT >= 33) { /* Android 13.0 (TIRAMISU) */
|
|
197
|
+
mContext.registerReceiver(mUsbBroadcast, filter, Context.RECEIVER_EXPORTED);
|
|
198
|
+
} else {
|
|
199
|
+
mContext.registerReceiver(mUsbBroadcast, filter);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
|
|
203
|
+
handleUsbDeviceAttached(usbDevice);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
UsbManager getUSBManager() {
|
|
208
|
+
return mUsbManager;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private void shutdownUSB() {
|
|
212
|
+
try {
|
|
213
|
+
mContext.unregisterReceiver(mUsbBroadcast);
|
|
214
|
+
} catch (Exception e) {
|
|
215
|
+
// We may not have registered, that's okay
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
220
|
+
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
230
|
+
final int XB360_IFACE_SUBCLASS = 93;
|
|
231
|
+
final int XB360_IFACE_PROTOCOL = 1; // Wired
|
|
232
|
+
final int XB360W_IFACE_PROTOCOL = 129; // Wireless
|
|
233
|
+
final int[] SUPPORTED_VENDORS = {
|
|
234
|
+
0x0079, // GPD Win 2
|
|
235
|
+
0x044f, // Thrustmaster
|
|
236
|
+
0x045e, // Microsoft
|
|
237
|
+
0x046d, // Logitech
|
|
238
|
+
0x056e, // Elecom
|
|
239
|
+
0x06a3, // Saitek
|
|
240
|
+
0x0738, // Mad Catz
|
|
241
|
+
0x07ff, // Mad Catz
|
|
242
|
+
0x0e6f, // PDP
|
|
243
|
+
0x0f0d, // Hori
|
|
244
|
+
0x1038, // SteelSeries
|
|
245
|
+
0x11c9, // Nacon
|
|
246
|
+
0x12ab, // Unknown
|
|
247
|
+
0x1430, // RedOctane
|
|
248
|
+
0x146b, // BigBen
|
|
249
|
+
0x1532, // Razer Sabertooth
|
|
250
|
+
0x15e4, // Numark
|
|
251
|
+
0x162e, // Joytech
|
|
252
|
+
0x1689, // Razer Onza
|
|
253
|
+
0x1949, // Lab126, Inc.
|
|
254
|
+
0x1bad, // Harmonix
|
|
255
|
+
0x20d6, // PowerA
|
|
256
|
+
0x24c6, // PowerA
|
|
257
|
+
0x2c22, // Qanba
|
|
258
|
+
0x2dc8, // 8BitDo
|
|
259
|
+
0x3537, // GameSir
|
|
260
|
+
0x37d7, // Flydigi
|
|
261
|
+
0x9886, // ASTRO Gaming
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
|
|
265
|
+
usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS &&
|
|
266
|
+
(usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL ||
|
|
267
|
+
usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) {
|
|
268
|
+
int vendor_id = usbDevice.getVendorId();
|
|
269
|
+
for (int supportedVid : SUPPORTED_VENDORS) {
|
|
270
|
+
if (vendor_id == supportedVid) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterface) {
|
|
279
|
+
final int XB1_IFACE_SUBCLASS = 71;
|
|
280
|
+
final int XB1_IFACE_PROTOCOL = 208;
|
|
281
|
+
final int[] SUPPORTED_VENDORS = {
|
|
282
|
+
0x03f0, // HP
|
|
283
|
+
0x044f, // Thrustmaster
|
|
284
|
+
0x045e, // Microsoft
|
|
285
|
+
0x0738, // Mad Catz
|
|
286
|
+
0x0b05, // ASUS
|
|
287
|
+
0x0e6f, // PDP
|
|
288
|
+
0x0f0d, // Hori
|
|
289
|
+
0x10f5, // Turtle Beach
|
|
290
|
+
0x1532, // Razer Wildcat
|
|
291
|
+
0x20d6, // PowerA
|
|
292
|
+
0x24c6, // PowerA
|
|
293
|
+
0x294b, // Snakebyte
|
|
294
|
+
0x2dc8, // 8BitDo
|
|
295
|
+
0x2e24, // Hyperkin
|
|
296
|
+
0x2e95, // SCUF
|
|
297
|
+
0x3285, // Nacon
|
|
298
|
+
0x3537, // GameSir
|
|
299
|
+
0x366c, // ByoWave
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
if (usbInterface.getId() == 0 &&
|
|
303
|
+
usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC &&
|
|
304
|
+
usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS &&
|
|
305
|
+
usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) {
|
|
306
|
+
int vendor_id = usbDevice.getVendorId();
|
|
307
|
+
for (int supportedVid : SUPPORTED_VENDORS) {
|
|
308
|
+
if (vendor_id == supportedVid) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private void handleUsbDeviceAttached(UsbDevice usbDevice) {
|
|
317
|
+
connectHIDDeviceUSB(usbDevice);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private void handleUsbDeviceDetached(UsbDevice usbDevice) {
|
|
321
|
+
List<Integer> devices = new ArrayList<Integer>();
|
|
322
|
+
for (HIDDevice device : mDevicesById.values()) {
|
|
323
|
+
if (usbDevice.equals(device.getDevice())) {
|
|
324
|
+
devices.add(device.getId());
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
for (int id : devices) {
|
|
328
|
+
HIDDevice device = mDevicesById.get(id);
|
|
329
|
+
mDevicesById.remove(id);
|
|
330
|
+
device.shutdown();
|
|
331
|
+
HIDDeviceDisconnected(id);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) {
|
|
336
|
+
for (HIDDevice device : mDevicesById.values()) {
|
|
337
|
+
if (usbDevice.equals(device.getDevice())) {
|
|
338
|
+
boolean opened = false;
|
|
339
|
+
if (permission_granted) {
|
|
340
|
+
opened = device.open();
|
|
341
|
+
}
|
|
342
|
+
HIDDeviceOpenResult(device.getId(), opened);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
private void connectHIDDeviceUSB(UsbDevice usbDevice) {
|
|
348
|
+
synchronized (this) {
|
|
349
|
+
int interface_mask = 0;
|
|
350
|
+
for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) {
|
|
351
|
+
UsbInterface usbInterface = usbDevice.getInterface(interface_index);
|
|
352
|
+
if (isHIDDeviceInterface(usbDevice, usbInterface)) {
|
|
353
|
+
// Check to see if we've already added this interface
|
|
354
|
+
// This happens with the Xbox Series X controller which has a duplicate interface 0, which is inactive
|
|
355
|
+
int interface_id = usbInterface.getId();
|
|
356
|
+
if ((interface_mask & (1 << interface_id)) != 0) {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
interface_mask |= (1 << interface_id);
|
|
360
|
+
|
|
361
|
+
HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index);
|
|
362
|
+
int id = device.getId();
|
|
363
|
+
mDevicesById.put(id, device);
|
|
364
|
+
HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
private void initializeBluetooth() {
|
|
371
|
+
Log.d(TAG, "Initializing Bluetooth");
|
|
372
|
+
|
|
373
|
+
if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ &&
|
|
374
|
+
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
|
|
375
|
+
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&
|
|
380
|
+
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
|
|
381
|
+
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
|
|
386
|
+
Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Find bonded bluetooth controllers and create SteamControllers for them
|
|
391
|
+
mBluetoothManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
|
|
392
|
+
if (mBluetoothManager == null) {
|
|
393
|
+
// This device doesn't support Bluetooth.
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
BluetoothAdapter btAdapter = mBluetoothManager.getAdapter();
|
|
398
|
+
if (btAdapter == null) {
|
|
399
|
+
// This device has Bluetooth support in the codebase, but has no available adapters.
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Get our bonded devices.
|
|
404
|
+
for (BluetoothDevice device : btAdapter.getBondedDevices()) {
|
|
405
|
+
|
|
406
|
+
Log.d(TAG, "Bluetooth device available: " + device);
|
|
407
|
+
if (isSteamController(device)) {
|
|
408
|
+
connectBluetoothDevice(device);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// NOTE: These don't work on Chromebooks, to my undying dismay.
|
|
414
|
+
IntentFilter filter = new IntentFilter();
|
|
415
|
+
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
|
416
|
+
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
|
417
|
+
if (Build.VERSION.SDK_INT >= 33) { /* Android 13.0 (TIRAMISU) */
|
|
418
|
+
mContext.registerReceiver(mBluetoothBroadcast, filter, Context.RECEIVER_EXPORTED);
|
|
419
|
+
} else {
|
|
420
|
+
mContext.registerReceiver(mBluetoothBroadcast, filter);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (mIsChromebook) {
|
|
424
|
+
mHandler = new Handler(Looper.getMainLooper());
|
|
425
|
+
mLastBluetoothDevices = new ArrayList<BluetoothDevice>();
|
|
426
|
+
|
|
427
|
+
// final HIDDeviceManager finalThis = this;
|
|
428
|
+
// mHandler.postDelayed(new Runnable() {
|
|
429
|
+
// @Override
|
|
430
|
+
// public void run() {
|
|
431
|
+
// finalThis.chromebookConnectionHandler();
|
|
432
|
+
// }
|
|
433
|
+
// }, 5000);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
private void shutdownBluetooth() {
|
|
438
|
+
try {
|
|
439
|
+
mContext.unregisterReceiver(mBluetoothBroadcast);
|
|
440
|
+
} catch (Exception e) {
|
|
441
|
+
// We may not have registered, that's okay
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly.
|
|
446
|
+
// This function provides a sort of dummy version of that, watching for changes in the
|
|
447
|
+
// connected devices and attempting to add controllers as things change.
|
|
448
|
+
void chromebookConnectionHandler() {
|
|
449
|
+
if (!mIsChromebook) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
ArrayList<BluetoothDevice> disconnected = new ArrayList<BluetoothDevice>();
|
|
454
|
+
ArrayList<BluetoothDevice> connected = new ArrayList<BluetoothDevice>();
|
|
455
|
+
|
|
456
|
+
List<BluetoothDevice> currentConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
|
|
457
|
+
|
|
458
|
+
for (BluetoothDevice bluetoothDevice : currentConnected) {
|
|
459
|
+
if (!mLastBluetoothDevices.contains(bluetoothDevice)) {
|
|
460
|
+
connected.add(bluetoothDevice);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
for (BluetoothDevice bluetoothDevice : mLastBluetoothDevices) {
|
|
464
|
+
if (!currentConnected.contains(bluetoothDevice)) {
|
|
465
|
+
disconnected.add(bluetoothDevice);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
mLastBluetoothDevices = currentConnected;
|
|
470
|
+
|
|
471
|
+
for (BluetoothDevice bluetoothDevice : disconnected) {
|
|
472
|
+
disconnectBluetoothDevice(bluetoothDevice);
|
|
473
|
+
}
|
|
474
|
+
for (BluetoothDevice bluetoothDevice : connected) {
|
|
475
|
+
connectBluetoothDevice(bluetoothDevice);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
final HIDDeviceManager finalThis = this;
|
|
479
|
+
mHandler.postDelayed(new Runnable() {
|
|
480
|
+
@Override
|
|
481
|
+
public void run() {
|
|
482
|
+
finalThis.chromebookConnectionHandler();
|
|
483
|
+
}
|
|
484
|
+
}, 10000);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
|
488
|
+
Log.v(TAG, "connectBluetoothDevice device=" + bluetoothDevice);
|
|
489
|
+
synchronized (this) {
|
|
490
|
+
if (mBluetoothDevices.containsKey(bluetoothDevice)) {
|
|
491
|
+
Log.v(TAG, "Steam controller with address " + bluetoothDevice + " already exists, attempting reconnect");
|
|
492
|
+
|
|
493
|
+
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
|
|
494
|
+
device.reconnect();
|
|
495
|
+
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
HIDDeviceBLESteamController device = new HIDDeviceBLESteamController(this, bluetoothDevice);
|
|
499
|
+
int id = device.getId();
|
|
500
|
+
mBluetoothDevices.put(bluetoothDevice, device);
|
|
501
|
+
mDevicesById.put(id, device);
|
|
502
|
+
|
|
503
|
+
// The Steam Controller will mark itself connected once initialization is complete
|
|
504
|
+
}
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
|
509
|
+
synchronized (this) {
|
|
510
|
+
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
|
|
511
|
+
if (device == null)
|
|
512
|
+
return;
|
|
513
|
+
|
|
514
|
+
int id = device.getId();
|
|
515
|
+
mBluetoothDevices.remove(bluetoothDevice);
|
|
516
|
+
mDevicesById.remove(id);
|
|
517
|
+
device.shutdown();
|
|
518
|
+
HIDDeviceDisconnected(id);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
boolean isSteamController(BluetoothDevice bluetoothDevice) {
|
|
523
|
+
// Sanity check. If you pass in a null device, by definition it is never a Steam Controller.
|
|
524
|
+
if (bluetoothDevice == null) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// If the device has no local name, we really don't want to try an equality check against it.
|
|
529
|
+
if (bluetoothDevice.getName() == null) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Steam Controllers will always support Bluetooth Low Energy
|
|
534
|
+
if ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) == 0) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Match on the name either the original Steam Controller or the new second-generation one advertise with.
|
|
539
|
+
return bluetoothDevice.getName().equals("SteamController") || bluetoothDevice.getName().startsWith("Steam Ctrl");
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
private void close() {
|
|
543
|
+
shutdownUSB();
|
|
544
|
+
shutdownBluetooth();
|
|
545
|
+
synchronized (this) {
|
|
546
|
+
for (HIDDevice device : mDevicesById.values()) {
|
|
547
|
+
device.shutdown();
|
|
548
|
+
}
|
|
549
|
+
mDevicesById.clear();
|
|
550
|
+
mBluetoothDevices.clear();
|
|
551
|
+
HIDDeviceReleaseCallback();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
public void setFrozen(boolean frozen) {
|
|
556
|
+
synchronized (this) {
|
|
557
|
+
for (HIDDevice device : mDevicesById.values()) {
|
|
558
|
+
device.setFrozen(frozen);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
564
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
565
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
566
|
+
|
|
567
|
+
private HIDDevice getDevice(int id) {
|
|
568
|
+
synchronized (this) {
|
|
569
|
+
HIDDevice result = mDevicesById.get(id);
|
|
570
|
+
if (result == null) {
|
|
571
|
+
Log.v(TAG, "No device for id: " + id);
|
|
572
|
+
Log.v(TAG, "Available devices: " + mDevicesById.keySet());
|
|
573
|
+
}
|
|
574
|
+
return result;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
579
|
+
////////// JNI interface functions
|
|
580
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
581
|
+
|
|
582
|
+
boolean initialize(boolean usb, boolean bluetooth) {
|
|
583
|
+
Log.v(TAG, "initialize(" + usb + ", " + bluetooth + ")");
|
|
584
|
+
|
|
585
|
+
if (usb) {
|
|
586
|
+
initializeUSB();
|
|
587
|
+
}
|
|
588
|
+
if (bluetooth) {
|
|
589
|
+
initializeBluetooth();
|
|
590
|
+
}
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
boolean openDevice(int deviceID) {
|
|
595
|
+
Log.v(TAG, "openDevice deviceID=" + deviceID);
|
|
596
|
+
HIDDevice device = getDevice(deviceID);
|
|
597
|
+
if (device == null) {
|
|
598
|
+
HIDDeviceDisconnected(deviceID);
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Look to see if this is a USB device and we have permission to access it
|
|
603
|
+
UsbDevice usbDevice = device.getDevice();
|
|
604
|
+
if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) {
|
|
605
|
+
HIDDeviceOpenPending(deviceID);
|
|
606
|
+
try {
|
|
607
|
+
final int FLAG_MUTABLE = 0x02000000; // PendingIntent.FLAG_MUTABLE, but don't require SDK 31
|
|
608
|
+
int flags;
|
|
609
|
+
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
|
610
|
+
flags = FLAG_MUTABLE;
|
|
611
|
+
} else {
|
|
612
|
+
flags = 0;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
|
|
616
|
+
intent.setPackage(mContext.getPackageName());
|
|
617
|
+
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
|
|
618
|
+
} catch (Exception e) {
|
|
619
|
+
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
|
|
620
|
+
HIDDeviceOpenResult(deviceID, false);
|
|
621
|
+
}
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
try {
|
|
626
|
+
return device.open();
|
|
627
|
+
} catch (Exception e) {
|
|
628
|
+
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
629
|
+
}
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
int writeReport(int deviceID, byte[] report, boolean feature) {
|
|
634
|
+
try {
|
|
635
|
+
//Log.v(TAG, "writeReport deviceID=" + deviceID + " length=" + report.length);
|
|
636
|
+
HIDDevice device;
|
|
637
|
+
device = getDevice(deviceID);
|
|
638
|
+
if (device == null) {
|
|
639
|
+
HIDDeviceDisconnected(deviceID);
|
|
640
|
+
return -1;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return device.writeReport(report, feature);
|
|
644
|
+
} catch (Exception e) {
|
|
645
|
+
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
646
|
+
}
|
|
647
|
+
return -1;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
boolean readReport(int deviceID, byte[] report, boolean feature) {
|
|
651
|
+
try {
|
|
652
|
+
//Log.v(TAG, "readReport deviceID=" + deviceID);
|
|
653
|
+
HIDDevice device;
|
|
654
|
+
device = getDevice(deviceID);
|
|
655
|
+
if (device == null) {
|
|
656
|
+
HIDDeviceDisconnected(deviceID);
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return device.readReport(report, feature);
|
|
661
|
+
} catch (Exception e) {
|
|
662
|
+
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
663
|
+
}
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
void closeDevice(int deviceID) {
|
|
668
|
+
try {
|
|
669
|
+
Log.v(TAG, "closeDevice deviceID=" + deviceID);
|
|
670
|
+
HIDDevice device;
|
|
671
|
+
device = getDevice(deviceID);
|
|
672
|
+
if (device == null) {
|
|
673
|
+
HIDDeviceDisconnected(deviceID);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
device.close();
|
|
678
|
+
} catch (Exception e) {
|
|
679
|
+
Log.e(TAG, "Got exception: " + Log.getStackTraceString(e));
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
685
|
+
/////////////// Native methods
|
|
686
|
+
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
687
|
+
|
|
688
|
+
private native void HIDDeviceRegisterCallback();
|
|
689
|
+
private native void HIDDeviceReleaseCallback();
|
|
690
|
+
|
|
691
|
+
native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID);
|
|
692
|
+
native void HIDDeviceOpenPending(int deviceID);
|
|
693
|
+
native void HIDDeviceOpenResult(int deviceID, boolean opened);
|
|
694
|
+
native void HIDDeviceDisconnected(int deviceID);
|
|
695
|
+
|
|
696
|
+
native void HIDDeviceInputReport(int deviceID, byte[] report);
|
|
697
|
+
native void HIDDeviceReportResponse(int deviceID, byte[] report);
|
|
698
|
+
}
|