--- /dev/null
+/*
+ * This file is part of the sigrok-androidutils project.
+ *
+ * Copyright (C) 2016 Marcus Comstedt <marcus@mc.pp.se>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sigrok.androidutils;
+
+public interface UsbEventListener
+{
+ public void onUsbDeviceAction(String name, boolean removed);
+}
--- /dev/null
+/*
+ * This file is part of the sigrok-androidutils project.
+ *
+ * Copyright (C) 2016 Marcus Comstedt <marcus@mc.pp.se>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sigrok.androidutils;
+
+final class UsbEventListenerStub implements UsbEventListener
+{
+ public native void onUsbDeviceAction(String name, boolean removed);
+}
--- /dev/null
+/*
+ * This file is part of the sigrok-androidutils project.
+ *
+ * Copyright (C) 2016 Marcus Comstedt <marcus@mc.pp.se>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sigrok.androidutils;
+
+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.UsbManager;
+import android.util.Log;
+
+final class UsbEventMonitor
+{
+ private final Context context;
+ private final UsbManager manager;
+ private final UsbEventListener listener;
+ private final BroadcastReceiver permReceiver;
+ private final BroadcastReceiver hotplugReceiver;
+ private final IntentFilter permFilter;
+ private final IntentFilter hotplugFilter;
+
+ UsbEventMonitor(Context context, UsbManager manager, UsbEventListener listener)
+ {
+ this.context = context;
+ this.manager = manager;
+ this.listener = listener;
+ permReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (UsbSupplicant.ACTION_USB_PERMISSION.equals(action)) {
+ permissionCallback((UsbDevice)intent.getParcelableExtra(
+ UsbManager.EXTRA_DEVICE), intent.getBooleanExtra(
+ UsbManager.EXTRA_PERMISSION_GRANTED, false));
+ }
+ }
+ };
+ hotplugReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null && UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
+ attachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
+ } else if (intent != null && UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
+ detachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
+ }
+ }
+ };
+ permFilter = new IntentFilter(UsbSupplicant.ACTION_USB_PERMISSION);
+ hotplugFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+ hotplugFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ }
+
+ synchronized void start()
+ {
+ context.registerReceiver(permReceiver, permFilter);
+ context.registerReceiver(hotplugReceiver, hotplugFilter);
+ }
+
+ synchronized void stop()
+ {
+ context.unregisterReceiver(hotplugReceiver);
+ context.unregisterReceiver(permReceiver);
+ }
+
+ private void permissionCallback(UsbDevice dev, boolean granted)
+ {
+ Log.d("UsbEventMonitor", "permission " +
+ (granted ? "granted" : "denied") + " for device " + dev);
+ addRemoveDevice(dev, !granted);
+ }
+
+ private void attachCallback(UsbDevice dev)
+ {
+ Log.d("UsbEventMonitor", "device " + dev + "added");
+ if (manager.hasPermission(dev))
+ addRemoveDevice(dev, false);
+ }
+
+ private void detachCallback(UsbDevice dev)
+ {
+ Log.d("UsbEventMonitor", "device " + dev + "removed");
+ addRemoveDevice(dev, true);
+ }
+
+ private synchronized void addRemoveDevice(UsbDevice dev, boolean removed)
+ {
+ listener.onUsbDeviceAction(dev.getDeviceName(), removed);
+ }
+}
public final class UsbHelper
{
private static UsbManager manager;
+ private static Context context;
+ private static UsbEventMonitor eventMonitor;
public static void setContext(Context ctx)
{
+ context = ctx;
if (ctx == null)
manager = null;
else
return (conn == null ? -1 : conn.getFileDescriptor());
}
+ private static synchronized void startEventMonitor(Context context, UsbManager manager, UsbEventListener listener)
+ {
+ if (eventMonitor != null) {
+ eventMonitor.stop();
+ eventMonitor = null;
+ }
+ if (context == null) {
+ Log.w("UsbHelper", "no context");
+ return;
+ }
+ if (manager == null) {
+ Log.w("UsbHelper", "no manager");
+ return;
+ }
+ eventMonitor = new UsbEventMonitor(context, manager, listener);
+ eventMonitor.start();
+ }
+
+ private static synchronized void stopEventMonitor(Context context)
+ {
+ if (eventMonitor != null) {
+ eventMonitor.stop();
+ eventMonitor = null;
+ }
+ }
+
+ private static String[] scanDevices(UsbManager manager)
+ {
+ if (manager == null) {
+ Log.w("UsbHelper", "no manager");
+ return null;
+ }
+ HashMap<String,UsbDevice> devlist = manager.getDeviceList();
+ if (devlist == null)
+ return null;
+ String[] list = devlist.keySet().toArray(new String[devlist.size()]);
+ return list;
+ }
+
public static int open(String name, int mode)
{
try {
return -1;
}
}
+
+ public static void startEventMonitor(UsbEventListener listener)
+ {
+ try {
+ startEventMonitor(context, manager, listener);
+ } catch (Exception e) {
+ Log.w("UsbHelper", "caught exception " + e);
+ }
+ }
+
+ public static void stopEventMonitor()
+ {
+ try {
+ stopEventMonitor(context);
+ } catch (Exception e) {
+ Log.w("UsbHelper", "caught exception " + e);
+ }
+ }
+
+ public static String[] scanDevices()
+ {
+ try {
+ return scanDevices(manager);
+ } catch (Exception e) {
+ Log.w("UsbHelper", "caught exception " + e);
+ return null;
+ }
+ }
}