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