import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.usb.descriptors.UsbDescriptor;
import com.android.server.usb.descriptors.UsbDescriptorParser;
import com.android.server.usb.descriptors.UsbDeviceDescriptor;
import com.android.server.usb.descriptors.report.TextReportCanvas;
String mDeviceAddress;
static final int CONNECT = 0;
- static final int DISCONNECT = 1;
+ static final int CONNECT_BADPARSE = 1;
+ static final int CONNECT_BADDEVICE = 2;
+ static final int DISCONNECT = -1;
+
final int mMode;
final byte[] mDescriptors;
}
void dumpShort(IndentingPrintWriter pw) {
- if (mMode == CONNECT) {
- pw.println(formatTime() + " Connect " + mDeviceAddress);
+ if (mMode != DISCONNECT) {
+ pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
UsbDeviceDescriptor deviceDescriptor = parser.getDeviceDescriptor();
}
}
- void dumpLong(IndentingPrintWriter pw) {
- if (mMode == CONNECT) {
- pw.println(formatTime() + " Connect " + mDeviceAddress);
+ void dumpTree(IndentingPrintWriter pw) {
+ if (mMode != DISCONNECT) {
+ pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
StringBuilder stringBuilder = new StringBuilder();
UsbDescriptorsTree descriptorTree = new UsbDescriptorsTree();
pw.println(formatTime() + " Disconnect " + mDeviceAddress);
}
}
+
+ void dumpList(IndentingPrintWriter pw) {
+ if (mMode != DISCONNECT) {
+ pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
+ UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
+ StringBuilder stringBuilder = new StringBuilder();
+ TextReportCanvas canvas = new TextReportCanvas(parser, stringBuilder);
+ for (UsbDescriptor descriptor : parser.getDescriptors()) {
+ descriptor.report(canvas);
+ }
+ pw.println(stringBuilder.toString());
+
+ pw.println("isHeadset[in: " + parser.isInputHeadset()
+ + " , out: " + parser.isOutputHeadset() + "]");
+ } else {
+ pw.println(formatTime() + " Disconnect " + mDeviceAddress);
+ }
+ }
+
+ private static final int kDumpBytesPerLine = 16;
+
+ void dumpRaw(IndentingPrintWriter pw) {
+ if (mMode != DISCONNECT) {
+ pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
+ int length = mDescriptors.length;
+ pw.println("Raw Descriptors " + length + " bytes");
+ int dataOffset = 0;
+ for (int line = 0; line < length / kDumpBytesPerLine; line++) {
+ StringBuilder sb = new StringBuilder();
+ for (int offset = 0; offset < kDumpBytesPerLine; offset++) {
+ sb.append("0x")
+ .append(String.format("0x%02X", mDescriptors[dataOffset++]))
+ .append(" ");
+ }
+ pw.println(sb.toString());
+ }
+
+ // remainder
+ StringBuilder sb = new StringBuilder();
+ while (dataOffset < length) {
+ sb.append("0x")
+ .append(String.format("0x%02X", mDescriptors[dataOffset++]))
+ .append(" ");
+ }
+ pw.println(sb.toString());
+ } else {
+ pw.println(formatTime() + " Disconnect " + mDeviceAddress);
+ }
+ }
}
/*
ConnectionRecord rec =
new ConnectionRecord(deviceAddress, mode, rawDescriptors);
mConnections.add(rec);
- if (mode == ConnectionRecord.CONNECT) {
+ if (mode != ConnectionRecord.DISCONNECT) {
mLastConnect = rec;
}
}
if (parser.parseDescriptors(descriptors)) {
UsbDevice newDevice = parser.toAndroidUsbDevice();
- mDevices.put(deviceAddress, newDevice);
-
- // It is fine to call this only for the current user as all broadcasts are sent to
- // all profiles of the user and the dialogs should only show once.
- ComponentName usbDeviceConnectionHandler = getUsbDeviceConnectionHandler();
- if (usbDeviceConnectionHandler == null) {
- getCurrentUserSettings().deviceAttached(newDevice);
+ if (newDevice == null) {
+ Slog.e(TAG, "Couldn't create UsbDevice object.");
+ // Tracking
+ addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADDEVICE,
+ parser.getRawDescriptors());
} else {
- getCurrentUserSettings().deviceAttachedForFixedHandler(newDevice,
- usbDeviceConnectionHandler);
+ mDevices.put(deviceAddress, newDevice);
+
+ // It is fine to call this only for the current user as all broadcasts are
+ // sent to all profiles of the user and the dialogs should only show once.
+ ComponentName usbDeviceConnectionHandler = getUsbDeviceConnectionHandler();
+ if (usbDeviceConnectionHandler == null) {
+ getCurrentUserSettings().deviceAttached(newDevice);
+ } else {
+ getCurrentUserSettings().deviceAttachedForFixedHandler(newDevice,
+ usbDeviceConnectionHandler);
+ }
+
+ // Headset?
+ boolean isInputHeadset = parser.isInputHeadset();
+ boolean isOutputHeadset = parser.isOutputHeadset();
+ Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
+ + " , out: " + isOutputHeadset + "]");
+
+ mUsbAlsaManager.usbDeviceAdded(newDevice, isInputHeadset, isOutputHeadset);
+
+ // Tracking
+ addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT,
+ parser.getRawDescriptors());
}
-
- // Headset?
- boolean isInputHeadset = parser.isInputHeadset();
- boolean isOutputHeadset = parser.isOutputHeadset();
- Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
- + " , out: " + isOutputHeadset + "]");
-
- mUsbAlsaManager.usbDeviceAdded(newDevice, isInputHeadset, isOutputHeadset);
-
- // Tracking
- addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT,
- parser.getRawDescriptors());
} else {
Slog.e(TAG, "Error parsing USB device descriptors for " + deviceAddress);
+ // Tracking
+ addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADPARSE,
+ parser.getRawDescriptors());
return false;
}
}
}
}
- public void dump(IndentingPrintWriter pw) {
+ /**
+ * Dump out various information about the state of USB device connections.
+ *
+ */
+ public void dump(IndentingPrintWriter pw, String[] args) {
pw.println("USB Host State:");
synchronized (mHandlerLock) {
if (mUsbDeviceConnectionHandler != null) {
pw.println(" " + name + ": " + mDevices.get(name));
}
+ // Connections
pw.println("" + mNumConnects + " total connects/disconnects");
pw.println("Last " + mConnections.size() + " connections/disconnections");
for (ConnectionRecord rec : mConnections) {
rec.dumpShort(pw);
}
- if (mLastConnect != null) {
- pw.println("Last Connected USB Device:");
- mLastConnect.dumpLong(pw);
- }
}
mUsbAlsaManager.dump(pw);
}
+ /**
+ * Dump various descriptor data.
+ */
+ public void dumpDescriptors(IndentingPrintWriter pw, String[] args) {
+ if (mLastConnect != null) {
+ pw.println("Last Connected USB Device:");
+ if (args.length <= 1 || args[1].equals("-dump-short")) {
+ mLastConnect.dumpShort(pw);
+ } else if (args[1].equals("-dump-tree")) {
+ mLastConnect.dumpTree(pw);
+ } else if (args[1].equals("-dump-list")) {
+ mLastConnect.dumpList(pw);
+ } else if (args[1].equals("-dump-raw")) {
+ mLastConnect.dumpRaw(pw);
+ }
+ } else {
+ pw.println("No USB Devices have been connected.");
+ }
+ }
+
private native void monitorUsbHostBus();
private native ParcelFileDescriptor nativeOpenDevice(String deviceAddress);
}
mDeviceManager.dump(pw);
}
if (mHostManager != null) {
- mHostManager.dump(pw);
+ mHostManager.dump(pw, args);
}
if (mPortManager != null) {
mPortManager.dump(pw);
mAlsaManager.dump(pw);
mSettingsManager.dump(pw);
- } else if (args.length == 4 && "set-port-roles".equals(args[0])) {
+ } else if ("set-port-roles".equals(args[0]) && args.length == 4) {
final String portId = args[1];
final int powerRole;
switch (args[2]) {
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 3 && "add-port".equals(args[0])) {
+ } else if ("add-port".equals(args[0]) && args.length == 3) {
final String portId = args[1];
final int supportedModes;
switch (args[2]) {
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 5 && "connect-port".equals(args[0])) {
+ } else if ("connect-port".equals(args[0]) && args.length == 5) {
final String portId = args[1];
final int mode;
final boolean canChangeMode = args[2].endsWith("?");
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 2 && "disconnect-port".equals(args[0])) {
+ } else if ("disconnect-port".equals(args[0]) && args.length == 2) {
final String portId = args[1];
if (mPortManager != null) {
mPortManager.disconnectSimulatedPort(portId, pw);
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 2 && "remove-port".equals(args[0])) {
+ } else if ("remove-port".equals(args[0]) && args.length == 2) {
final String portId = args[1];
if (mPortManager != null) {
mPortManager.removeSimulatedPort(portId, pw);
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 1 && "reset".equals(args[0])) {
+ } else if ("reset".equals(args[0]) && args.length == 1) {
if (mPortManager != null) {
mPortManager.resetSimulation(pw);
pw.println();
mPortManager.dump(pw);
}
- } else if (args.length == 1 && "ports".equals(args[0])) {
+ } else if ("ports".equals(args[0]) && args.length == 1) {
if (mPortManager != null) {
mPortManager.dump(pw);
}
+ } else if ("dump-descriptors".equals(args[0])) {
+ mHostManager.dumpDescriptors(pw, args);
} else {
pw.println("Dump current USB state or issue command:");
pw.println(" ports");
pw.println(" dumpsys usb add-port \"matrix\" ufp");
pw.println(" dumpsys usb connect-port \"matrix\" ufp sink device");
pw.println(" dumpsys usb reset");
+ pw.println();
+ pw.println("Example USB device descriptors:");
+ pw.println(" dumpsys usb dump-descriptors -dump-short");
+ pw.println(" dumpsys usb dump-descriptors -dump-tree");
+ pw.println(" dumpsys usb dump-descriptors -dump-list");
+ pw.println(" dumpsys usb dump-descriptors -dump-raw");
}
} finally {
Binder.restoreCallingIdentity(ident);
import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbDevice;
+import android.util.Log;
import com.android.server.usb.descriptors.report.ReportCanvas;
import com.android.server.usb.descriptors.report.UsbStrings;
*/
public final class UsbDeviceDescriptor extends UsbDescriptor {
private static final String TAG = "UsbDeviceDescriptor";
+ private static final boolean DEBUG = false;
public static final int USBSPEC_1_0 = 0x0100;
public static final int USBSPEC_1_1 = 0x0110;
* @hide
*/
public UsbDevice toAndroid(UsbDescriptorParser parser) {
+ if (DEBUG) {
+ Log.d(TAG, "toAndroid()");
+ }
+
String mfgName = parser.getDescriptorString(mMfgIndex);
String prodName = parser.getDescriptorString(mProductIndex);
+ if (DEBUG) {
+ Log.d(TAG, " mfgName:" + mfgName + " prodName:" + prodName);
+ }
// Create version string in "%.%" format
String versionString =
Integer.toString(mDeviceRelease >> 8) + "." + (mDeviceRelease & 0xFF);
String serialStr = parser.getDescriptorString(mSerialNum);
+ if (DEBUG) {
+ Log.d(TAG, " versionString:" + versionString + " serialStr:" + serialStr);
+ }
UsbDevice device = new UsbDevice(parser.getDeviceAddr(), mVendorID, mProductID,
mDevClass, mDevSubClass,
mProtocol, mfgName, prodName,
versionString, serialStr);
UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()];
+ Log.d(TAG, " " + configs.length + " configs");
for (int index = 0; index < mConfigDescriptors.size(); index++) {
configs[index] = mConfigDescriptors.get(index).toAndroid(parser);
}