aboutsummaryrefslogtreecommitdiff
path: root/android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java')
-rw-r--r--android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java b/android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java
new file mode 100644
index 0000000..f0e6c62
--- /dev/null
+++ b/android/WALT/app/src/main/java/org/chromium/latency/walt/BaseUsbConnection.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.chromium.latency.walt;
+
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbDeviceConnection;
+import android.hardware.usb.UsbManager;
+import android.support.v4.content.LocalBroadcastManager;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+public abstract class BaseUsbConnection {
+ private static final String USB_PERMISSION_RESPONSE_INTENT = "usb-permission-response";
+ private static final String CONNECT_INTENT = "org.chromium.latency.walt.CONNECT";
+
+ protected SimpleLogger logger;
+ protected Context context;
+ private LocalBroadcastManager broadcastManager;
+ private BroadcastReceiver currentConnectReceiver;
+ private WaltConnection.ConnectionStateListener connectionStateListener;
+
+ private UsbManager usbManager;
+ protected UsbDevice usbDevice = null;
+ protected UsbDeviceConnection usbConnection;
+
+ public BaseUsbConnection(Context context) {
+ this.context = context;
+ usbManager = (UsbManager) this.context.getSystemService(Context.USB_SERVICE);
+ logger = SimpleLogger.getInstance(context);
+ broadcastManager = LocalBroadcastManager.getInstance(context);
+ }
+
+ public abstract int getVid();
+ public abstract int getPid();
+
+ // Used to distinguish between bootloader and normal mode that differ by PID
+ // TODO: change intent strings to reduce dependence on PID
+ protected abstract boolean isCompatibleUsbDevice(UsbDevice usbDevice);
+
+ public void onDisconnect() {
+ if (connectionStateListener != null) {
+ connectionStateListener.onDisconnect();
+ }
+ }
+
+ public void onConnect() {
+ if (connectionStateListener != null) {
+ connectionStateListener.onConnect();
+ }
+ }
+
+
+ private String getConnectIntent() {
+ return CONNECT_INTENT + getVid() + ":" + getPid();
+ }
+
+ private String getUsbPermissionResponseIntent() {
+ return USB_PERMISSION_RESPONSE_INTENT + getVid() + ":" + getPid();
+ }
+
+ public boolean isConnected() {
+ return usbConnection != null;
+ }
+
+ public void registerConnectCallback(final Runnable r) {
+ if (currentConnectReceiver != null) {
+ broadcastManager.unregisterReceiver(currentConnectReceiver);
+ currentConnectReceiver = null;
+ }
+
+ if (isConnected()) {
+ r.run();
+ return;
+ }
+
+ currentConnectReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ broadcastManager.unregisterReceiver(this);
+ r.run();
+ }
+ };
+ broadcastManager.registerReceiver(currentConnectReceiver,
+ new IntentFilter(getConnectIntent()));
+ }
+
+ public void connect() {
+ UsbDevice usbDevice = findUsbDevice();
+ connect(usbDevice);
+ }
+
+ public void connect(UsbDevice usbDevice) {
+ if (usbDevice == null) {
+ logger.log("Device not found.");
+ return;
+ }
+
+ if (!isCompatibleUsbDevice(usbDevice)) {
+ logger.log("Not a valid device");
+ return;
+ }
+
+ this.usbDevice = usbDevice;
+
+ // Request permission
+ // This displays a dialog asking user for permission to use the device.
+ // No dialog is displayed if the permission was already given before or the app started as a
+ // result of intent filter when the device was plugged in.
+
+ PendingIntent permissionIntent = PendingIntent.getBroadcast(context, 0,
+ new Intent(getUsbPermissionResponseIntent()), 0);
+ context.registerReceiver(respondToUsbPermission,
+ new IntentFilter(getUsbPermissionResponseIntent()));
+ logger.log("Requesting permission for USB device.");
+ usbManager.requestPermission(this.usbDevice, permissionIntent);
+ }
+
+ public void disconnect() {
+ onDisconnect();
+
+ usbConnection.close();
+ usbConnection = null;
+ usbDevice = null;
+
+ context.unregisterReceiver(disconnectReceiver);
+ }
+
+ private BroadcastReceiver disconnectReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ if (isConnected() && BaseUsbConnection.this.usbDevice.equals(usbDevice)) {
+ logger.log("WALT was detached");
+ disconnect();
+ }
+ }
+ };
+
+ private BroadcastReceiver respondToUsbPermission = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ if (usbDevice == null) {
+ logger.log("USB device was not properly opened");
+ return;
+ }
+
+ if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) &&
+ usbDevice.equals(intent.getParcelableExtra(UsbManager.EXTRA_DEVICE))){
+ usbConnection = usbManager.openDevice(usbDevice);
+
+ BaseUsbConnection.this.context.registerReceiver(disconnectReceiver,
+ new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));
+
+ onConnect();
+
+ broadcastManager.sendBroadcast(new Intent(getConnectIntent()));
+ } else {
+ logger.log("Could not get permission to open the USB device");
+ }
+ BaseUsbConnection.this.context.unregisterReceiver(respondToUsbPermission);
+ }
+ };
+
+ public UsbDevice findUsbDevice() {
+
+ logger.log(String.format("Looking for TeensyUSB VID=0x%x PID=0x%x", getVid(), getPid()));
+
+ HashMap<String, UsbDevice> deviceHash = usbManager.getDeviceList();
+ if (deviceHash.size() == 0) {
+ logger.log("No connected USB devices found");
+ return null;
+ }
+
+ logger.log("Found " + deviceHash.size() + " connected USB devices:");
+
+ UsbDevice usbDevice = null;
+
+ for (String key : deviceHash.keySet()) {
+
+ UsbDevice dev = deviceHash.get(key);
+
+ String msg = String.format(Locale.US,
+ "USB Device: %s, VID:PID - %x:%x, %d interfaces",
+ key, dev.getVendorId(), dev.getProductId(), dev.getInterfaceCount()
+ );
+
+ if (isCompatibleUsbDevice(dev)) {
+ usbDevice = dev;
+ msg = "Using " + msg;
+ } else {
+ msg = "Skipping " + msg;
+ }
+
+ logger.log(msg);
+ }
+ return usbDevice;
+ }
+
+ public void setConnectionStateListener(WaltConnection.ConnectionStateListener connectionStateListener) {
+ this.connectionStateListener = connectionStateListener;
+ }
+}