]> sigrok.org Git - sigrok-androidutils.git/blame - src/org/sigrok/androidutils/UsbSupplicant.java
Minor whitespace and cosmetic fixes.
[sigrok-androidutils.git] / src / org / sigrok / androidutils / UsbSupplicant.java
CommitLineData
ea3ce762 1/*
5de7ce63 2 * This file is part of the sigrok-androidutils project.
ea3ce762
MC
3 *
4 * Copyright (C) 2014 Marcus Comstedt <marcus@mc.pp.se>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20package org.sigrok.androidutils;
21
22import android.app.PendingIntent;
23import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.res.Resources;
28import android.content.res.XmlResourceParser;
29import android.hardware.usb.UsbDevice;
30import android.hardware.usb.UsbInterface;
31import android.hardware.usb.UsbManager;
32import android.util.Log;
33import java.io.IOException;
34import java.util.HashMap;
35import java.util.Vector;
36import org.xmlpull.v1.XmlPullParser;
37import org.xmlpull.v1.XmlPullParserException;
38
39public class UsbSupplicant
40{
6f1c3a93 41 private static final String ACTION_USB_PERMISSION =
ea3ce762
MC
42 "org.sigrok.androidutils.USB_PERMISSION";
43
6f1c3a93
UH
44 protected final Context context;
45 protected final UsbManager manager;
46 private final BroadcastReceiver permReceiver;
47 private final BroadcastReceiver hotplugReceiver;
48 private final IntentFilter permFilter;
49 private final IntentFilter hotplugFilter;
50 private final Vector<DeviceFilter> deviceFilters;
51
52 // The code in the following inner class is taken from AOSP,
53 // which is licensed under the Apache License, Version 2.0.
54 private static class DeviceFilter {
55 // USB Vendor ID (or -1 for unspecified)
56 public final int mVendorId;
57 // USB Product ID (or -1 for unspecified)
58 public final int mProductId;
59 // USB device or interface class (or -1 for unspecified)
60 public final int mClass;
61 // USB device subclass (or -1 for unspecified)
62 public final int mSubclass;
63 // USB device protocol (or -1 for unspecified)
64 public final int mProtocol;
65
66 public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol) {
67 mVendorId = vid;
68 mProductId = pid;
69 mClass = clasz;
70 mSubclass = subclass;
71 mProtocol = protocol;
72 }
73
74 public DeviceFilter(UsbDevice device) {
75 mVendorId = device.getVendorId();
76 mProductId = device.getProductId();
77 mClass = device.getDeviceClass();
78 mSubclass = device.getDeviceSubclass();
79 mProtocol = device.getDeviceProtocol();
80 }
81
82 public static DeviceFilter read(XmlPullParser parser)
83 throws XmlPullParserException, IOException {
84 int vendorId = -1;
85 int productId = -1;
86 int deviceClass = -1;
87 int deviceSubclass = -1;
88 int deviceProtocol = -1;
89
90 int count = parser.getAttributeCount();
91 for (int i = 0; i < count; i++) {
92 String name = parser.getAttributeName(i);
93 // All attribute values are ints
94 int value = Integer.parseInt(parser.getAttributeValue(i));
95
96 if ("vendor-id".equals(name)) {
97 vendorId = value;
98 } else if ("product-id".equals(name)) {
99 productId = value;
100 } else if ("class".equals(name)) {
101 deviceClass = value;
102 } else if ("subclass".equals(name)) {
103 deviceSubclass = value;
104 } else if ("protocol".equals(name)) {
105 deviceProtocol = value;
106 }
107 }
108 return new DeviceFilter(vendorId, productId,
109 deviceClass, deviceSubclass, deviceProtocol);
ea3ce762 110 }
6f1c3a93
UH
111
112 private boolean matches(int clasz, int subclass, int protocol) {
113 return ((mClass == -1 || clasz == mClass) &&
114 (mSubclass == -1 || subclass == mSubclass) &&
115 (mProtocol == -1 || protocol == mProtocol));
116 }
117
118 public boolean matches(UsbDevice device) {
119 if (mVendorId != -1 && device.getVendorId() != mVendorId)
120 return false;
121 if (mProductId != -1 && device.getProductId() != mProductId)
122 return false;
123
124 // Check device class/subclass/protocol.
125 if (matches(device.getDeviceClass(), device.getDeviceSubclass(),
126 device.getDeviceProtocol()))
127 return true;
128
129 // If device doesn't match, check the interfaces.
130 int count = device.getInterfaceCount();
131 for (int i = 0; i < count; i++) {
132 UsbInterface intf = device.getInterface(i);
133 if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(),
134 intf.getInterfaceProtocol()))
135 return true;
136 }
137
138 return false;
139 }
140
ea3ce762 141 @Override
6f1c3a93
UH
142 public String toString() {
143 return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId +
144 ",mClass=" + mClass + ",mSubclass=" + mSubclass +
145 ",mProtocol=" + mProtocol + "]";
ea3ce762 146 }
ea3ce762 147 }
6f1c3a93
UH
148
149 public UsbSupplicant(Context ctx, int device_filter_resource)
150 {
151 context = ctx;
152 manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
153 permReceiver = new BroadcastReceiver() {
154 @Override
155 public void onReceive(Context context, Intent intent) {
156 String action = intent.getAction();
157 if (ACTION_USB_PERMISSION.equals(action)) {
158 permissionCallback((UsbDevice)intent.getParcelableExtra(
159 UsbManager.EXTRA_DEVICE), intent.getBooleanExtra(
160 UsbManager.EXTRA_PERMISSION_GRANTED, false));
161 }
162 }
163 };
164 hotplugReceiver = new BroadcastReceiver() {
165 @Override
166 public void onReceive(Context context, Intent intent) {
167 if (intent != null && UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
168 attachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
169 } else if (intent != null && UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
170 detachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
171 }
172 }
173 };
174 permFilter = new IntentFilter(ACTION_USB_PERMISSION);
175 hotplugFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
176 hotplugFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
177 deviceFilters = new Vector<DeviceFilter>();
178 addDeviceFilters(ctx.getResources(), device_filter_resource);
179 }
180
181 private void addDeviceFilters(Resources res, int res_id)
182 {
183 XmlResourceParser parser = res.getXml(res_id);
184 if (parser == null) {
185 Log.w("UsbSupplicant", "Unable to get device filter resource");
186 return;
187 }
188 deviceFilters.clear();
189 try {
190 while (parser.next() != XmlPullParser.END_DOCUMENT) {
191 if (parser.getEventType() == XmlPullParser.START_TAG) {
192 if ("usb-device".equals(parser.getName()))
193 deviceFilters.add(DeviceFilter.read(parser));
194 }
195 }
196 } catch (IOException e) {
197 Log.wtf("UsbSupplicant",
198 "Failed to parse device filter resource", e);
199 } catch (XmlPullParserException e) {
200 Log.wtf("UsbSupplicant",
201 "Failed to parse device filter resource", e);
ea3ce762 202 }
ea3ce762 203 }
6f1c3a93
UH
204
205 protected boolean interresting(UsbDevice dev)
206 {
207 if (dev == null)
208 return false;
209
210 for (DeviceFilter f : deviceFilters)
211 if (f.matches(dev))
212 return true;
213
214 return false;
ea3ce762 215 }
6f1c3a93
UH
216
217 protected void askFor(UsbDevice dev)
218 {
219 manager.requestPermission(dev, PendingIntent.getBroadcast(context, 0,
220 new Intent(ACTION_USB_PERMISSION), 0));
ea3ce762 221 }
ea3ce762 222
6f1c3a93
UH
223 public void start()
224 {
225 context.registerReceiver(permReceiver, permFilter);
226 context.registerReceiver(hotplugReceiver, hotplugFilter);
227 HashMap<String,UsbDevice> devlist = manager.getDeviceList();
228 for (UsbDevice dev : devlist.values()) {
229 if (interresting(dev) && !manager.hasPermission(dev)) {
230 Log.d("UsbSupplicant", "found interresting device " + dev);
231 askFor(dev);
232 }
233 }
234 }
235
236 public void stop()
237 {
238 context.unregisterReceiver(hotplugReceiver);
239 context.unregisterReceiver(permReceiver);
240 }
241
242 protected void permissionCallback(UsbDevice dev, boolean granted)
243 {
244 Log.d("UsbSupplicant", "permission " +
245 (granted ? "granted" : "denied") + " for device " + dev);
246 }
247
248 protected void attachCallback(UsbDevice dev)
249 {
250 if (interresting(dev) && !manager.hasPermission(dev))
251 askFor(dev);
252 }
253
254 protected void detachCallback(UsbDevice dev)
255 {
256 }
ea3ce762 257}