*/
package com.android.server.usb.descriptors;
+// Framework builds and Android Studio builds use different imports for NonNull.
+// This one for Framework builds
import android.annotation.NonNull;
+// this one in the AndroidStudio project
+// import android.support.annotation.NonNull;
/**
* @hide
* but with the capability to "back up" in situations where the parser discovers that a
* UsbDescriptor has overrun its length.
*/
-public class ByteStream {
+public final class ByteStream {
private static final String TAG = "ByteStream";
/** The byte array being wrapped */
}
/**
+ * @return the next byte from the stream and advances the stream and the read count. Note
+ * that this is an unsigned byte encoded in a Java int.
+ * @throws IndexOutOfBoundsException
+ */
+ public int getUnsignedByte() {
+ if (available() > 0) {
+ mReadCount++;
+ return mBytes[mIndex++] & 0x000000FF;
+ } else {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+ /**
* Reads 2 bytes in *little endian format* from the stream and composes a 16-bit integer.
* As we are storing the 2-byte value in a 4-byte integer, the upper 2 bytes are always
* 0, essentially making the returned value *unsigned*.
* next 2 bytes in the stream.
* @throws IndexOutOfBoundsException
*/
- public int unpackUsbWord() {
+ public int unpackUsbShort() {
if (available() >= 2) {
- int b0 = getByte();
- int b1 = getByte();
- return ((b1 << 8) & 0x0000FF00) | (b0 & 0x000000FF);
+ int b0 = getUnsignedByte();
+ int b1 = getUnsignedByte();
+ return (b1 << 8) | b0;
} else {
throw new IndexOutOfBoundsException();
}
*/
public int unpackUsbTriple() {
if (available() >= 3) {
- int b0 = getByte();
- int b1 = getByte();
- int b2 = getByte();
- return ((b2 << 16) & 0x00FF0000) | ((b1 << 8) & 0x0000FF00) | (b0 & 0x000000FF);
+ int b0 = getUnsignedByte();
+ int b1 = getUnsignedByte();
+ int b2 = getUnsignedByte();
+ return (b2 << 16) | (b1 << 8) | b0;
} else {
throw new IndexOutOfBoundsException();
}
}
/**
+ * Reads 4 bytes in *little endian format* from the stream and composes a 32-bit integer.
+ * @return The 32-bit integer encoded by the next 4 bytes in the stream.
+ * @throws IndexOutOfBoundsException
+ */
+ public int unpackUsbInt() {
+ if (available() >= 4) {
+ int b0 = getUnsignedByte();
+ int b1 = getUnsignedByte();
+ int b2 = getUnsignedByte();
+ int b3 = getUnsignedByte();
+ return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+ } else {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+ /**
* Advances the logical position in the stream. Affects the running count also.
* @param numBytes The number of bytes to advance.
* @throws IndexOutOfBoundsException
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Interface Header.
* see audio10.pdf section 4.3.2
*/
-public class UsbACHeader extends UsbACInterface {
- private static final String TAG = "ACHeader";
+public final class Usb10ACHeader extends UsbACHeaderInterface {
+ private static final String TAG = "Usb10ACHeader";
- private int mADCRelease; // 3:2 Audio Device Class Specification Release (BCD).
- private int mTotalLength; // 5:2 Total number of bytes returned for the class-specific
- // AudioControl interface descriptor. Includes the combined length
- // of this descriptor header and all Unit and Terminal descriptors.
private byte mNumInterfaces = 0; // 7:1 The number of AudioStreaming and MIDIStreaming
// interfaces in the Audio Interface Collection to which this
// AudioControl interface belongs: n
// numbers associate with this endpoint
private byte mControls; // Vers 2.0 thing
- public UsbACHeader(int length, byte type, byte subtype, byte subclass) {
- super(length, type, subtype, subclass);
- }
-
- public int getADCRelease() {
- return mADCRelease;
- }
-
- public int getTotalLength() {
- return mTotalLength;
+ public Usb10ACHeader(int length, byte type, byte subtype, byte subclass, int spec) {
+ super(length, type, subtype, subclass, spec);
}
public byte getNumInterfaces() {
@Override
public int parseRawDescriptors(ByteStream stream) {
- mADCRelease = stream.unpackUsbWord();
- mTotalLength = stream.unpackUsbWord();
+ mTotalLength = stream.unpackUsbShort();
if (mADCRelease >= 0x200) {
mControls = stream.getByte();
} else {
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ int numInterfaces = getNumInterfaces();
+ StringBuilder sb = new StringBuilder();
+ sb.append("" + numInterfaces + " Interfaces");
+ if (numInterfaces > 0) {
+ sb.append(" [");
+ byte[] interfaceNums = getInterfaceNums();
+ if (interfaceNums != null) {
+ for (int index = 0; index < numInterfaces; index++) {
+ sb.append("" + interfaceNums[index]);
+ if (index < numInterfaces - 1) {
+ sb.append(" ");
+ }
+ }
+ }
+ sb.append("]");
+ }
+ canvas.writeListItem(sb.toString());
+ canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls()));
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Input Terminal interface.
* see audio10.pdf section 4.3.2.1
*/
-public class UsbACInputTerminal extends UsbACTerminal {
- private static final String TAG = "ACInputTerminal";
+public final class Usb10ACInputTerminal extends UsbACTerminal {
+ private static final String TAG = "Usb10ACInputTerminal";
private byte mNrChannels; // 7:1 1 Channel (0x01)
// Number of logical output channels in the
private byte mChannelNames; // 10:1 Unused (0x00)
private byte mTerminal; // 11:1 Unused (0x00)
- public UsbACInputTerminal(int length, byte type, byte subtype, byte subclass) {
+ public Usb10ACInputTerminal(int length, byte type, byte subtype, byte subclass) {
super(length, type, subtype, subclass);
}
super.parseRawDescriptors(stream);
mNrChannels = stream.getByte();
- mChannelConfig = stream.unpackUsbWord();
+ mChannelConfig = stream.unpackUsbShort();
mChannelNames = stream.getByte();
mTerminal = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Associated Terminal: "
+ + ReportCanvas.getHexString(getAssocTerminal()));
+ canvas.writeListItem("" + getNrChannels() + " Chans. Config: "
+ + ReportCanvas.getHexString(getChannelConfig()));
+ canvas.closeList();
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Mixer Interface.
+ * see audio10.pdf section 4.3.2.3
+ */
+public final class Usb10ACMixerUnit extends UsbACMixerUnit {
+ private static final String TAG = "Usb10ACMixerUnit";
+
+ private int mChannelConfig; // Spatial location of output channels
+ private byte mChanNameID; // First channel name string descriptor ID
+ private byte[] mControls; // bitmasks of which controls are present for each channel
+ private byte mNameID; // string descriptor ID of mixer name
+
+ public Usb10ACMixerUnit(int length, byte type, byte subtype, byte subClass) {
+ super(length, type, subtype, subClass);
+ }
+
+ public int getChannelConfig() {
+ return mChannelConfig;
+ }
+
+ public byte getChanNameID() {
+ return mChanNameID;
+ }
+
+ public byte[] getControls() {
+ return mControls;
+ }
+
+ public byte getNameID() {
+ return mNameID;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ super.parseRawDescriptors(stream);
+
+ mChannelConfig = stream.unpackUsbShort();
+ mChanNameID = stream.getByte();
+
+ int controlArraySize = calcControlArraySize(mNumInputs, mNumOutputs);
+ mControls = new byte[controlArraySize];
+ for (int index = 0; index < controlArraySize; index++) {
+ mControls[index] = stream.getByte();
+ }
+
+ mNameID = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.writeParagraph("Mixer Unit", false);
+ canvas.openList();
+
+ canvas.writeListItem("Unit ID: " + ReportCanvas.getHexString(getUnitID()));
+ byte numInputs = getNumInputs();
+ byte[] inputIDs = getInputIDs();
+ canvas.openListItem();
+ canvas.write("Num Inputs: " + numInputs + " [");
+ for (int input = 0; input < numInputs; input++) {
+ canvas.write("" + ReportCanvas.getHexString(inputIDs[input]));
+ if (input < numInputs - 1) {
+ canvas.write(" ");
+ }
+ }
+ canvas.write("]");
+ canvas.closeListItem();
+
+ canvas.writeListItem("Num Outputs: " + getNumOutputs());
+ canvas.writeListItem("Channel Config: " + ReportCanvas.getHexString(getChannelConfig()));
+
+ byte[] controls = getControls();
+ canvas.openListItem();
+ canvas.write("Controls: " + controls.length + " [");
+ for (int ctrl = 0; ctrl < controls.length; ctrl++) {
+ canvas.write("" + controls[ctrl]);
+ if (ctrl < controls.length - 1) {
+ canvas.write(" ");
+ }
+ }
+ canvas.write("]");
+ canvas.closeListItem();
+ canvas.closeList();
+ }
+}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Output Terminal Interface.
* see audio10.pdf section 4.3.2.2
*/
-public class UsbACOutputTerminal extends UsbACTerminal {
- private static final String TAG = "ACOutputTerminal";
+public final class Usb10ACOutputTerminal extends UsbACTerminal {
+ private static final String TAG = "Usb10ACOutputTerminal";
private byte mSourceID; // 7:1 From Input Terminal. (0x01)
private byte mTerminal; // 8:1 Unused.
- public UsbACOutputTerminal(int length, byte type, byte subtype, byte subClass) {
+ public Usb10ACOutputTerminal(int length, byte type, byte subtype, byte subClass) {
super(length, type, subtype, subClass);
}
mTerminal = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Source ID: " + ReportCanvas.getHexString(getSourceID()));
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Format I interface.
* see Frmts10.pdf section 2.2
*/
-public class UsbASFormatI extends UsbASFormat {
- private static final String TAG = "ASFormatI";
+public final class Usb10ASFormatI extends UsbASFormat {
+ private static final String TAG = "Usb10ASFormatI";
private byte mNumChannels; // 4:1
private byte mSubframeSize; // 5:1 frame size in bytes
// min & max rates otherwise mSamFreqType rates.
// All 3-byte values. All rates in Hz
- public UsbASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ public Usb10ASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) {
super(length, type, subtype, formatType, subclass);
}
return mSampleFreqType;
}
+ @Override
public int[] getSampleRates() {
return mSampleRates;
}
@Override
+ public int[] getBitDepths() {
+ int[] depths = {mBitResolution};
+ return depths;
+ }
+
+ @Override
+ public int[] getChannelCounts() {
+ int[] counts = {mNumChannels};
+ return counts;
+ }
+
+ @Override
public int parseRawDescriptors(ByteStream stream) {
mNumChannels = stream.getByte();
mSubframeSize = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("" + getNumChannels() + " Channels.");
+ canvas.writeListItem("Subframe Size: " + getSubframeSize());
+ canvas.writeListItem("Bit Resolution: " + getBitResolution());
+ byte sampleFreqType = getSampleFreqType();
+ int[] sampleRates = getSampleRates();
+ canvas.writeListItem("Sample Freq Type: " + sampleFreqType);
+ canvas.openList();
+ if (sampleFreqType == 0) {
+ canvas.writeListItem("min: " + sampleRates[0]);
+ canvas.writeListItem("max: " + sampleRates[1]);
+ } else {
+ for (int index = 0; index < sampleFreqType; index++) {
+ canvas.writeListItem("" + sampleRates[index]);
+ }
+ }
+ canvas.closeList();
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Format II interface.
* see Frmts10.pdf section 2.3
*/
-public class UsbASFormatII extends UsbASFormat {
- private static final String TAG = "ASFormatII";
+public final class Usb10ASFormatII extends UsbASFormat {
+ private static final String TAG = "Usb10ASFormatII";
private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per second this
// interface can handle. Expressed in kbits/s.
// the min & max rates. otherwise mSamFreqType rates.
// All 3-byte values. All rates in Hz
- public UsbASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ public Usb10ASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) {
super(length, type, subtype, formatType, subclass);
}
@Override
public int parseRawDescriptors(ByteStream stream) {
- mMaxBitRate = stream.unpackUsbWord();
- mSamplesPerFrame = stream.unpackUsbWord();
+ mMaxBitRate = stream.unpackUsbShort();
+ mSamplesPerFrame = stream.unpackUsbShort();
mSamFreqType = stream.getByte();
int numFreqs = mSamFreqType == 0 ? 2 : mSamFreqType;
mSampleRates = new int[numFreqs];
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Max Bit Rate: " + getMaxBitRate());
+ canvas.writeListItem("Samples Per Frame: " + getMaxBitRate());
+ byte sampleFreqType = getSamFreqType();
+ int[] sampleRates = getSampleRates();
+ canvas.writeListItem("Sample Freq Type: " + sampleFreqType);
+ canvas.openList();
+ if (sampleFreqType == 0) {
+ canvas.writeListItem("min: " + sampleRates[0]);
+ canvas.writeListItem("max: " + sampleRates[1]);
+ } else {
+ for (int index = 0; index < sampleFreqType; index++) {
+ canvas.writeListItem("" + sampleRates[index]);
+ }
+ }
+ canvas.closeList();
+
+ canvas.closeList();
+ }
+
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
* An audio class-specific General interface.
* see audio10.pdf section 4.5.2
*/
-public class UsbASGeneral extends UsbACInterface {
- private static final String TAG = "ACGeneral";
+public final class Usb10ASGeneral extends UsbACInterface {
+ private static final String TAG = "Usb10ASGeneral";
// audio10.pdf - section 4.5.2
private byte mTerminalLink; // 3:1 The Terminal ID of the Terminal to which the endpoint
private int mFormatTag; // 5:2 The Audio Data Format that has to be used to communicate
// with this interface.
- public UsbASGeneral(int length, byte type, byte subtype, byte subclass) {
+ public Usb10ASGeneral(int length, byte type, byte subtype, byte subclass) {
super(length, type, subtype, subclass);
}
public int parseRawDescriptors(ByteStream stream) {
mTerminalLink = stream.getByte();
mDelay = stream.getByte();
- mFormatTag = stream.unpackUsbWord();
+ mFormatTag = stream.unpackUsbShort();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Delay: " + mDelay);
+ canvas.writeListItem("Terminal Link: " + mTerminalLink);
+ canvas.writeListItem("Format: " + UsbStrings.getAudioFormatName(mFormatTag) + " - "
+ + ReportCanvas.getHexString(mFormatTag));
+ canvas.closeList();
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Header descriptor.
+ * see Audio20.pdf section 4.7.2 Class-Specific AC Interface Descriptor
+ */
+public final class Usb20ACHeader extends UsbACHeaderInterface {
+ private static final String TAG = "Usb20ACHeader";
+
+ private byte mCategory; // 5:1 Constant, indicating the primary use of this audio function.
+ // See audio20.pdf Appendix A.7, “Audio Function Category Codes.”
+ private byte mControls; // 8:1 See audio20.pdf Table 4-5.
+
+ public Usb20ACHeader(int length, byte type, byte subtype, byte subclass, int spec) {
+ super(length, type, subtype, subclass, spec);
+ }
+
+ public byte getCategory() {
+ return mCategory;
+ }
+
+ public byte getControls() {
+ return mControls;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ mCategory = stream.getByte();
+ mTotalLength = stream.unpackUsbShort();
+ mControls = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Category: " + ReportCanvas.getHexString(getCategory()));
+ canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls()));
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Input Terminal interface.
+ * see Audio20.pdf section 3.13.2 Input Terminal
+ */
+public final class Usb20ACInputTerminal extends UsbACTerminal {
+ private static final String TAG = "Usb20ACInputTerminal";
+
+ // See Audio20.pdf - Table 4-9
+ // Always 17 bytes
+ private byte mClkSourceID; // 7:1 - ID of the Clock Entity to which this Input
+ // Terminal is connected.
+ private byte mNumChannels; // 8:1 - Number of logical output channels in the
+ // Terminal’s output audio channel cluster.
+ private int mChanConfig; // 9:4 - Describes the spatial location of the
+ // logical channels.
+ private byte mChanNames; // 13:1 - Index of a string descriptor, describing the
+ // name of the first logical channel.
+ private int mControls; // 14:2 - Bitmask (see Audio20.pdf Table 4-9)
+ private byte mTerminalName; // 16:1 - Index of a string descriptor, describing the
+ // Input Terminal.
+
+ public Usb20ACInputTerminal(int length, byte type, byte subtype, byte subclass) {
+ super(length, type, subtype, subclass);
+ }
+
+ public byte getClkSourceID() {
+ return mClkSourceID;
+ }
+
+ public byte getNumChannels() {
+ return mNumChannels;
+ }
+
+ public int getChanConfig() {
+ return mChanConfig;
+ }
+
+ public int getControls() {
+ return mControls;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ super.parseRawDescriptors(stream);
+
+ mClkSourceID = stream.getByte();
+ mNumChannels = stream.getByte();
+ mChanConfig = stream.unpackUsbInt();
+ mChanNames = stream.getByte();
+ mControls = stream.unpackUsbShort();
+ mTerminalName = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Clock Source: " + getClkSourceID());
+ canvas.writeListItem("" + getNumChannels() + " Channels. Config: "
+ + ReportCanvas.getHexString(getChanConfig()));
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+/**
+ * @hide
+ * An audio class-specific Mixer Unit interface.
+ * see Audio20.pdf section 4.7.2.6 Mixer Unit Descriptor
+ */
+public final class Usb20ACMixerUnit extends UsbACMixerUnit {
+ private static final String TAG = "Usb20ACMixerUnit";
+
+ private int mChanConfig; // 6+p:4 Describes the spatial location of the
+ // logical channels.
+ private byte mChanNames; // 10+p:1 Index of a string descriptor, describing the
+ // name of the first logical channel.
+ private byte[] mControls; // 11+p:N bitmasks of which controls are present for each channel
+ // for N, see UsbACMixerUnit.calcControlArraySize()
+ private byte mControlsMask; // 11+p+N:1 bitmasks of which controls are present for each channel
+ private byte mNameID; // 12+p+N:1 Index of a string descriptor, describing the
+ // Mixer Unit.
+
+ public Usb20ACMixerUnit(int length, byte type, byte subtype, byte subClass) {
+ super(length, type, subtype, subClass);
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ super.parseRawDescriptors(stream);
+
+ mChanConfig = stream.unpackUsbInt();
+ mChanNames = stream.getByte();
+ int controlArraySize = calcControlArraySize(mNumInputs, mNumOutputs);
+ mControls = new byte[controlArraySize];
+ for (int index = 0; index < controlArraySize; index++) {
+ mControls[index] = stream.getByte();
+ }
+ mControlsMask = stream.getByte();
+ mNameID = stream.getByte();
+
+ return mLength;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Output Terminal interface.
+ * see Audio20.pdf section 3.13.3 Output Terminal
+ */
+public final class Usb20ACOutputTerminal extends UsbACTerminal {
+ private static final String TAG = "Usb20ACOutputTerminal";
+
+ // Audio20.pdf - section 4.7.2.5, Table 4-10
+ // Always 12 bytes
+ private byte mSourceID; // 7:1 - ID of the Unit or Terminal to which this
+ // Terminal is connected.
+ private byte mClkSoureID; // 8:1 - ID of the Clock Entity to which this Output
+ // Terminal is connected.
+ private int mControls; // 9:2 - see Audio20.pdf Table 4-10
+ private byte mTerminalID; // 11:1 - Index of a string descriptor, describing the
+
+ public Usb20ACOutputTerminal(int length, byte type, byte subtype, byte subClass) {
+ super(length, type, subtype, subClass);
+ }
+
+ public byte getSourceID() {
+ return mSourceID;
+ }
+
+ public byte getClkSourceID() {
+ return mClkSoureID;
+ }
+
+ public int getControls() {
+ return mControls;
+ }
+
+ public byte getTerminalID() {
+ return mTerminalID;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ super.parseRawDescriptors(stream);
+
+ mSourceID = stream.getByte();
+ mClkSoureID = stream.getByte();
+ mControls = stream.unpackUsbShort();
+ mTerminalID = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Clock Source ID: " + getClkSourceID());
+ canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls()));
+ canvas.writeListItem("Terminal Name ID: " + getTerminalID());
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Format I interface.
+ * see Frmts20.pdf section 2.3.1.6 Type I Format Type Descriptor
+ */
+public final class Usb20ASFormatI extends UsbASFormat {
+ private static final String TAG = "Usb20ASFormatI";
+
+ // Frmts20.pdf Table 2-2: Type I Format Type Descriptor
+ private byte mSubSlotSize; // 4:1 The number of bytes occupied by one
+ // audio subslot. Can be 1, 2, 3 or 4.
+ private byte mBitResolution; // 5:1 The number of effectively used bits from
+ // the available bits in an audio subslot.
+
+ public Usb20ASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ super(length, type, subtype, formatType, subclass);
+ }
+
+ /**
+ * TBD
+ */
+ public byte getSubSlotSize() {
+ return mSubSlotSize;
+ }
+
+ /**
+ * TBD
+ */
+ public byte getBitResolution() {
+ return mBitResolution;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ mSubSlotSize = stream.getByte();
+ mBitResolution = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Subslot Size: " + getSubSlotSize());
+ canvas.writeListItem("Bit Resolution: " + getBitResolution());
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Format II interface.
+ * see Frmts20.pdf section 2.3.2.6 Type II Format Type Descriptor
+ */
+public final class Usb20ASFormatII extends UsbASFormat {
+ private static final String TAG = "Usb20ASFormatII";
+
+ // Frmts20.pdf Table 2-3: Type II Format Type Descriptor
+ private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per
+ // second this interface can handle in kbits/s.
+ private int mSlotsPerFrame; // 6:2 Indicates the number of PCM audio slots
+ // contained in one encoded audio frame.
+
+ /**
+ * TBD
+ */
+ public Usb20ASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ super(length, type, subtype, formatType, subclass);
+ }
+
+ /**
+ * TBD
+ */
+ public int getmaxBitRate() {
+ return mMaxBitRate;
+ }
+
+ /**
+ * TBD
+ */
+ public int getSlotsPerFrame() {
+ return mSlotsPerFrame;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ mMaxBitRate = stream.unpackUsbShort();
+ mSlotsPerFrame = stream.unpackUsbShort();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Max Bit Rate: " + getmaxBitRate());
+ canvas.writeListItem("slots Per Frame: " + getSlotsPerFrame());
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Format II interface.
+ * see Frmts20.pdf section 2.4.2.1 Extended Type II Format Type Descriptor
+ */
+public final class Usb20ASFormatIIEx extends UsbASFormat {
+ private static final String TAG = "Usb20ASFormatIIEx";
+
+ // Frmts20.pdf Table 2-7: Extended Type II Format Type Descriptor
+ private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per
+ // second this interface can handle in kbits/s
+ private int mSamplesPerFrame; // 6:2 Indicates the number of PCM audio
+ // samples contained in one encoded audio frame.
+ private byte mHeaderLength; // 8:1 Size of the Packet Header, in bytes.
+ private byte mSidebandProtocol; // 9:1 Constant, identifying the Side Band
+ // Protocol used for the Packet Header content.
+
+ public Usb20ASFormatIIEx(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ super(length, type, subtype, formatType, subclass);
+ }
+
+ public int getMaxBitRate() {
+ return mMaxBitRate;
+ }
+
+ public int getSamplesPerFrame() {
+ return mSamplesPerFrame;
+ }
+
+ public byte getHeaderLength() {
+ return mHeaderLength;
+ }
+
+ public byte getSidebandProtocol() {
+ return mSidebandProtocol;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ mMaxBitRate = stream.unpackUsbShort();
+ mSamplesPerFrame = stream.unpackUsbShort();
+ mHeaderLength = stream.getByte();
+ mSidebandProtocol = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Max Bit Rate: " + getMaxBitRate());
+ canvas.writeListItem("Samples Per Frame: " + getSamplesPerFrame());
+ canvas.writeListItem("Header Length: " + getHeaderLength());
+ canvas.writeListItem("Sideband Protocol: " + getSidebandProtocol());
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Format III interface.
+ * see Frmts20.pdf section 2.3.1.6 2.3.3.1 Type III Format Type Descriptor
+ */
+public final class Usb20ASFormatIII extends UsbASFormat {
+ private static final String TAG = "Usb20ASFormatIII";
+
+ // frmts20.pdf Table 2-4: Type III Format Type Descriptor
+ private byte mSubslotSize; // 4:1 The number of bytes occupied by one
+ // audio subslot. Must be set to two.
+ private byte mBitResolution; // 5:1 The number of effectively used bits from
+ // the available bits in an audio subframe.
+
+ public Usb20ASFormatIII(int length, byte type, byte subtype, byte formatType, byte subclass) {
+ super(length, type, subtype, formatType, subclass);
+ }
+
+ public byte getSubslotSize() {
+ return mSubslotSize;
+ }
+
+ public byte getBitResolution() {
+ return mBitResolution;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+ mSubslotSize = stream.getByte();
+ mBitResolution = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Subslot Size: " + getSubslotSize());
+ canvas.writeListItem("Bit Resolution: " + getBitResolution());
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * Audio20.pdf - 4.9.2 Class-Specific AS Interface Descriptor
+ * 16 bytes
+ */
+public final class Usb20ASGeneral extends UsbACInterface {
+ private static final String TAG = "Usb20ASGeneral";
+
+ // Audio20.pdf - Table 4-27
+ private byte mTerminalLink; // 3:1 The Terminal ID of the Terminal to which
+ // this interface is connected.
+ private byte mControls; // 4:1 see audio20.pdf Table 4-27
+ private byte mFormatType; // 5:1 Constant identifying the Format Type the
+ // AudioStreaming interface is using.
+ private int mFormats; // 6:4 The Audio Data Format(s) that can be
+ // used to communicate with this interface.
+ // See the USB Audio Data Formats
+ // document for further details.
+ private byte mNumChannels; // 10:1 Number of physical channels in the AS
+ // Interface audio channel cluster.
+ private int mChannelConfig; // 11:4 Describes the spatial location of the
+ // physical channels.
+ private byte mChannelNames; // 15:1 Index of a string descriptor, describing the
+ // name of the first physical channel.
+
+ public Usb20ASGeneral(int length, byte type, byte subtype, byte subclass) {
+ super(length, type, subtype, subclass);
+ }
+
+ public byte getTerminalLink() {
+ return mTerminalLink;
+ }
+
+ public byte getControls() {
+ return mControls;
+ }
+
+ public byte getFormatType() {
+ return mFormatType;
+ }
+
+ public int getFormats() {
+ return mFormats;
+ }
+
+ public byte getNumChannels() {
+ return mNumChannels;
+ }
+
+ public int getChannelConfig() {
+ return mChannelConfig;
+ }
+
+ public byte getChannelNames() {
+ return mChannelNames;
+ }
+
+ @Override
+ public int parseRawDescriptors(ByteStream stream) {
+
+ mTerminalLink = stream.getByte();
+ mControls = stream.getByte();
+ mFormatType = stream.getByte();
+ mFormats = stream.unpackUsbInt();
+ mNumChannels = stream.getByte();
+ mChannelConfig = stream.unpackUsbInt();
+ mChannelNames = stream.getByte();
+
+ return mLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Terminal Link: " + getTerminalLink());
+ canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls()));
+ canvas.writeListItem("Format Type: " + ReportCanvas.getHexString(getFormatType()));
+ canvas.writeListItem("Formats: " + ReportCanvas.getHexString(getFormats()));
+ canvas.writeListItem("Num Channels: " + getNumChannels());
+ canvas.writeListItem("Channel Config: " + ReportCanvas.getHexString(getChannelConfig()));
+ canvas.writeListItem("Channel Names String ID: " + getChannelNames());
+ canvas.closeList();
+ }
+}
* audio10.pdf section 4.4.2.1
*/
public class UsbACAudioControlEndpoint extends UsbACEndpoint {
- private static final String TAG = "ACAudioControlEndpoint";
+ private static final String TAG = "UsbACAudioControlEndpoint";
private byte mAddress; // 2:1 The address of the endpoint on the USB device.
// D7: Direction. 1 = IN endpoint
mAddress = stream.getByte();
mAttribs = stream.getByte();
- mMaxPacketSize = stream.unpackUsbWord();
+ mMaxPacketSize = stream.unpackUsbShort();
mInterval = stream.getByte();
return mLength;
* see audio10.pdf section 3.7.2
*/
public class UsbACAudioStreamEndpoint extends UsbACEndpoint {
- private static final String TAG = "ACAudioStreamEndpoint";
+ private static final String TAG = "UsbACAudioStreamEndpoint";
//TODO data fields...
public UsbACAudioStreamEndpoint(int length, byte type, byte subclass) {
* see audio10.pdf section 4.4.1.2
*/
abstract class UsbACEndpoint extends UsbDescriptor {
- private static final String TAG = "ACEndpoint";
+ private static final String TAG = "UsbACEndpoint";
protected final byte mSubclass; // from the mSubclass member of the "enclosing"
// Interface Descriptor, not the stream.
}
public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser,
- int length, byte type) {
+ int length, byte type) {
UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
byte subClass = interfaceDesc.getUsbSubclass();
switch (subClass) {
* An audio class-specific Feature Unit Interface
* see audio10.pdf section 3.5.5
*/
-public class UsbACFeatureUnit extends UsbACInterface {
- private static final String TAG = "ACFeatureUnit";
+public final class UsbACFeatureUnit extends UsbACInterface {
+ private static final String TAG = "UsbACFeatureUnit";
// audio10.pdf section 4.3.2.5
public static final int CONTROL_MASK_MUTE = 0x0001;
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An audio class-specific Interface Header super class.
+ * see audio10.pdf section 4.3.2 & Audio20.pdf section 4.7.2
+ */
+public abstract class UsbACHeaderInterface extends UsbACInterface {
+ private static final String TAG = "UsbACHeaderInterface";
+
+ protected int mADCRelease; // Audio Device Class Specification Release (BCD).
+ protected int mTotalLength; // Total number of bytes returned for the class-specific
+ // AudioControl interface descriptor. Includes the combined length
+ // of this descriptor header and all Unit and Terminal descriptors.
+
+ public UsbACHeaderInterface(
+ int length, byte type, byte subtype, byte subclass, int adcRelease) {
+ super(length, type, subtype, subclass);
+ mADCRelease = adcRelease;
+ }
+
+ public int getADCRelease() {
+ return mADCRelease;
+ }
+
+ public int getTotalLength() {
+ return mTotalLength;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Release: " + ReportCanvas.getBCDString(getADCRelease()));
+ canvas.writeListItem("Total Length: " + getTotalLength());
+ canvas.closeList();
+ }
+}
import android.util.Log;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
* An audio class-specific Interface.
* see audio10.pdf section 4.3.2
*/
public abstract class UsbACInterface extends UsbDescriptor {
- private static final String TAG = "ACInterface";
+ private static final String TAG = "UsbACInterface";
// Audio Control Subtypes
public static final byte ACI_UNDEFINED = 0;
public static final byte ACI_FEATURE_UNIT = 6;
public static final byte ACI_PROCESSING_UNIT = 7;
public static final byte ACI_EXTENSION_UNIT = 8;
+ // Not handled yet
+ public static final byte ACI_CLOCK_SOURCE = 0x0A;
+ public static final byte ACI_CLOCK_SELECTOR = 0x0B;
+ public static final byte ACI_CLOCK_MULTIPLIER = 0x0C;
+ public static final byte ACI_SAMPLE_RATE_CONVERTER = 0x0D;
// Audio Streaming Subtypes
public static final byte ASI_UNDEFINED = 0;
return mSubclass;
}
- private static UsbDescriptor allocAudioControlDescriptor(ByteStream stream,
- int length, byte type, byte subtype, byte subClass) {
+ private static UsbDescriptor allocAudioControlDescriptor(UsbDescriptorParser parser,
+ ByteStream stream, int length, byte type, byte subtype, byte subClass) {
switch (subtype) {
case ACI_HEADER:
- return new UsbACHeader(length, type, subtype, subClass);
+ {
+ int acInterfaceSpec = stream.unpackUsbShort();
+ parser.setACInterfaceSpec(acInterfaceSpec);
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ACHeader(length, type, subtype, subClass, acInterfaceSpec);
+ } else {
+ return new Usb10ACHeader(length, type, subtype, subClass, acInterfaceSpec);
+ }
+ }
case ACI_INPUT_TERMINAL:
- return new UsbACInputTerminal(length, type, subtype, subClass);
+ {
+ int acInterfaceSpec = parser.getACInterfaceSpec();
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ACInputTerminal(length, type, subtype, subClass);
+ } else {
+ return new Usb10ACInputTerminal(length, type, subtype, subClass);
+ }
+ }
case ACI_OUTPUT_TERMINAL:
- return new UsbACOutputTerminal(length, type, subtype, subClass);
+ {
+ int acInterfaceSpec = parser.getACInterfaceSpec();
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ACOutputTerminal(length, type, subtype, subClass);
+ } else {
+ return new Usb10ACOutputTerminal(length, type, subtype, subClass);
+ }
+ }
case ACI_SELECTOR_UNIT:
return new UsbACSelectorUnit(length, type, subtype, subClass);
return new UsbACFeatureUnit(length, type, subtype, subClass);
case ACI_MIXER_UNIT:
- return new UsbACMixerUnit(length, type, subtype, subClass);
+ {
+ int acInterfaceSpec = parser.getACInterfaceSpec();
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ACMixerUnit(length, type, subtype, subClass);
+ } else {
+ return new Usb10ACMixerUnit(length, type, subtype, subClass);
+ }
+ }
case ACI_PROCESSING_UNIT:
case ACI_EXTENSION_UNIT:
default:
Log.w(TAG, "Unknown Audio Class Interface subtype:0x"
+ Integer.toHexString(subtype));
- return null;
+ return new UsbACInterfaceUnparsed(length, type, subtype, subClass);
}
}
- private static UsbDescriptor allocAudioStreamingDescriptor(ByteStream stream,
- int length, byte type, byte subtype, byte subClass) {
+ private static UsbDescriptor allocAudioStreamingDescriptor(UsbDescriptorParser parser,
+ ByteStream stream, int length, byte type, byte subtype, byte subClass) {
+ //int spec = parser.getUsbSpec();
+ int acInterfaceSpec = parser.getACInterfaceSpec();
switch (subtype) {
case ASI_GENERAL:
- return new UsbASGeneral(length, type, subtype, subClass);
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ASGeneral(length, type, subtype, subClass);
+ } else {
+ return new Usb10ASGeneral(length, type, subtype, subClass);
+ }
case ASI_FORMAT_TYPE:
- return UsbASFormat.allocDescriptor(stream, length, type, subtype, subClass);
+ return UsbASFormat.allocDescriptor(parser, stream, length, type, subtype, subClass);
case ASI_FORMAT_SPECIFIC:
case ASI_UNDEFINED:
// Fall through until we implement that descriptor
case MSI_UNDEFINED:
- // break; Fall through until we implement this descriptor
default:
Log.w(TAG, "Unknown MIDI Streaming Interface subtype:0x"
+ Integer.toHexString(subtype));
byte subClass = interfaceDesc.getUsbSubclass();
switch (subClass) {
case AUDIO_AUDIOCONTROL:
- return allocAudioControlDescriptor(stream, length, type, subtype, subClass);
+ return allocAudioControlDescriptor(
+ parser, stream, length, type, subtype, subClass);
case AUDIO_AUDIOSTREAMING:
- return allocAudioStreamingDescriptor(stream, length, type, subtype, subClass);
+ return allocAudioStreamingDescriptor(
+ parser, stream, length, type, subtype, subClass);
case AUDIO_MIDISTREAMING:
return allocMidiStreamingDescriptor(length, type, subtype, subClass);
return null;
}
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ byte subClass = getSubclass();
+ String subClassName = UsbStrings.getACInterfaceSubclassName(subClass);
+
+ byte subtype = getSubtype();
+ String subTypeName = UsbStrings.getACControlInterfaceName(subtype);
+
+ canvas.openList();
+ canvas.writeListItem("Subclass: " + ReportCanvas.getHexString(subClass)
+ + " " + subClassName);
+ canvas.writeListItem("Subtype: " + ReportCanvas.getHexString(subtype) + " " + subTypeName);
+ canvas.closeList();
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors;
+
+/**
+ * @hide
+ * A holder class for as yet unparsed audio-class interfaces.
+ */
+public final class UsbACInterfaceUnparsed extends UsbACInterface {
+ private static final String TAG = "UsbACInterfaceUnparsed";
+
+ public UsbACInterfaceUnparsed(int length, byte type, byte subtype, byte subClass) {
+ super(length, type, subtype, subClass);
+ }
+}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Midi Endpoint.
* see midi10.pdf section 6.2.2
*/
-public class UsbACMidiEndpoint extends UsbACEndpoint {
- private static final String TAG = "ACMidiEndpoint";
+public final class UsbACMidiEndpoint extends UsbACEndpoint {
+ private static final String TAG = "UsbACMidiEndpoint";
private byte mNumJacks;
private byte[] mJackIds;
}
return mLength;
}
-}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.writeHeader(3, "AC Midi Endpoint: " + ReportCanvas.getHexString(getType())
+ + " Length: " + getLength());
+ canvas.openList();
+ canvas.writeListItem("" + getNumJacks() + " Jacks.");
+ canvas.closeList();
+ }
+}
\ No newline at end of file
*/
package com.android.server.usb.descriptors;
-/**
- * @hide
- * An audio class-specific Mixer Interface.
- * see audio10.pdf section 4.3.2.3
- */
public class UsbACMixerUnit extends UsbACInterface {
- private static final String TAG = "ACMixerUnit";
+ private static final String TAG = "UsbACMixerUnit";
- private byte mUnitID; // 3:1
- private byte mNumInputs; // 4:1 Number of Input Pins of this Unit.
- private byte[] mInputIDs; // 5...:1 ID of the Unit or Terminal to which the Input Pins
- // are connected.
- private byte mNumOutputs; // The number of output channels
- private int mChannelConfig; // Spacial location of output channels
- private byte mChanNameID; // First channel name string descriptor ID
- private byte[] mControls; // bitmasks of which controls are present for each channel
- private byte mNameID; // string descriptor ID of mixer name
+ protected byte mUnitID; // 3:1
+ protected byte mNumInputs; // 4:1 Number of Input Pins of this Unit.
+ protected byte[] mInputIDs; // 5...:1 ID of the Unit or Terminal to which the Input Pins
+ // are connected.
+ protected byte mNumOutputs; // The number of output channels
public UsbACMixerUnit(int length, byte type, byte subtype, byte subClass) {
super(length, type, subtype, subClass);
return mNumOutputs;
}
- public int getChannelConfig() {
- return mChannelConfig;
- }
-
- public byte getChanNameID() {
- return mChanNameID;
- }
-
- public byte[] getControls() {
- return mControls;
- }
-
- public byte getNameID() {
- return mNameID;
+ protected static int calcControlArraySize(int numInputs, int numOutputs) {
+ int totalChannels = numInputs * numOutputs;
+ return (totalChannels + 7) / 8;
}
@Override
mInputIDs[input] = stream.getByte();
}
mNumOutputs = stream.getByte();
- mChannelConfig = stream.unpackUsbWord();
- mChanNameID = stream.getByte();
-
- int controlArraySize;
- int totalChannels = mNumInputs * mNumOutputs;
- if (totalChannels % 8 == 0) {
- controlArraySize = totalChannels / 8;
- } else {
- controlArraySize = totalChannels / 8 + 1;
- }
- mControls = new byte[controlArraySize];
- for (int index = 0; index < controlArraySize; index++) {
- mControls[index] = stream.getByte();
- }
-
- mNameID = stream.getByte();
return mLength;
}
*/
package com.android.server.usb.descriptors;
+// import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Selector Unit Interface.
* see audio10.pdf section 4.3.2.4
*/
-public class UsbACSelectorUnit extends UsbACInterface {
- private static final String TAG = "ACSelectorUnit";
+public final class UsbACSelectorUnit extends UsbACInterface {
+ private static final String TAG = "UsbACSelectorUnit";
private byte mUnitID; // 3:1 Constant uniquely identifying the Unit within the audio function.
// This value is used in all requests to address this Unit.
return mLength;
}
+
+// @Override
+// public void report(ReportCanvas canvas) {
+// super.report(canvas);
+//
+// //TODO
+// }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
*/
public abstract class UsbACTerminal extends UsbACInterface {
+ private static final String TAG = "UsbACTerminal";
+
// Note that these fields are the same for both the
// audio class-specific Output Terminal Interface.(audio10.pdf section 4.3.2.2)
// and audio class-specific Input Terminal interface.(audio10.pdf section 4.3.2.1)
@Override
public int parseRawDescriptors(ByteStream stream) {
mTerminalID = stream.getByte();
- mTerminalType = stream.unpackUsbWord();
+ mTerminalType = stream.unpackUsbShort();
mAssocTerminal = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ int terminalType = getTerminalType();
+ canvas.writeListItem("Type: " + ReportCanvas.getHexString(terminalType) + ": "
+ + UsbStrings.getTerminalName(terminalType));
+ canvas.writeListItem("ID: " + ReportCanvas.getHexString(getTerminalID()));
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
* An audio class-specific Format Interface.
* Subclasses: UsbACFormatI and UsbACFormatII.
* see audio10.pdf section 4.5.3 & & Frmts10.pdf
*/
-public abstract class UsbASFormat extends UsbACInterface {
- private static final String TAG = "ASFormat";
+public class UsbASFormat extends UsbACInterface {
+ private static final String TAG = "UsbASFormat";
private final byte mFormatType; // 3:1 FORMAT_TYPE_*
- public static final byte FORMAT_TYPE_I = 1;
- public static final byte FORMAT_TYPE_II = 2;
+ public static final byte FORMAT_TYPE_I = 1;
+ public static final byte FORMAT_TYPE_II = 2;
+ // these showed up in USB 2.0
+ public static final byte FORMAT_TYPE_III = 3;
+ public static final byte FORMAT_TYPE_IV = 4;
+
+ // "extended" formats
+ public static final byte EXT_FORMAT_TYPE_I = (byte) 0x81;
+ public static final byte EXT_FORMAT_TYPE_II = (byte) 0x82;
+ public static final byte EXT_FORMAT_TYPE_III = (byte) 0x83;
public UsbASFormat(int length, byte type, byte subtype, byte formatType, byte mSubclass) {
super(length, type, subtype, mSubclass);
return mFormatType;
}
+ public int[] getSampleRates() {
+ return null;
+ }
+
+ public int[] getBitDepths() {
+ return null;
+ }
+
+ public int[] getChannelCounts() {
+ return null;
+ }
+
/**
* Allocates the audio-class format subtype associated with the format type read from the
* stream.
*/
- public static UsbDescriptor allocDescriptor(ByteStream stream, int length, byte type,
+ public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser,
+ ByteStream stream, int length, byte type,
byte subtype, byte subclass) {
byte formatType = stream.getByte();
- //TODO
- // There is an issue parsing format descriptors on (some) USB 2.0 pro-audio interfaces
- // Since we don't need this info for headset detection, just skip these descriptors
- // for now to avoid the (low) possibility of an IndexOutOfBounds exception.
+ int acInterfaceSpec = parser.getACInterfaceSpec();
+
switch (formatType) {
-// case FORMAT_TYPE_I:
-// return new UsbASFormatI(length, type, subtype, formatType, subclass);
-//
-// case FORMAT_TYPE_II:
-// return new UsbASFormatII(length, type, subtype, formatType, subclass);
+ case FORMAT_TYPE_I:
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ASFormatI(length, type, subtype, formatType, subclass);
+ } else {
+ return new Usb10ASFormatI(length, type, subtype, formatType, subclass);
+ }
+
+ case FORMAT_TYPE_II:
+ if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) {
+ return new Usb20ASFormatII(length, type, subtype, formatType, subclass);
+ } else {
+ return new Usb10ASFormatII(length, type, subtype, formatType, subclass);
+ }
+
+ // USB 2.0 Exclusive Format Types
+ case FORMAT_TYPE_III:
+ return new Usb20ASFormatIII(length, type, subtype, formatType, subclass);
+ case FORMAT_TYPE_IV:
+ //TODO - implement this type.
default:
- return null;
+ return new UsbASFormat(length, type, subtype, formatType, subclass);
}
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.write(UsbStrings.getFormatName(getFormatType()));
+ }
}
* A class that just walks the descriptors and does a hex dump of the contained values.
* Usefull as a debugging tool.
*/
-public class UsbBinaryParser {
+public final class UsbBinaryParser {
private static final String TAG = "UsbBinaryParser";
private static final boolean LOGGING = false;
// Log
if (LOGGING) {
- Log.i(TAG, "l:" + length + " t:" + Integer.toHexString(type) + " "
+ Log.i(TAG, "l: " + length + " t: " + Integer.toHexString(type) + " "
+ UsbStrings.getDescriptorName(type));
StringBuilder sb = new StringBuilder();
for (int index = 2; index < length; index++) {
} else {
// Screen Dump
builder.append("<p>");
- builder.append("<b> l:" + length
+ builder.append("<b> l: " + length
+ " t:0x" + Integer.toHexString(type) + " "
+ UsbStrings.getDescriptorName(type) + "</b><br>");
for (int index = 2; index < length; index++) {
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An USB Config Descriptor.
* see usb11.pdf section 9.6.2
*/
-public class UsbConfigDescriptor extends UsbDescriptor {
- private static final String TAG = "Config";
+public final class UsbConfigDescriptor extends UsbDescriptor {
+ private static final String TAG = "UsbConfigDescriptor";
private int mTotalLength; // 2:2 Total length in bytes of data returned
private byte mNumInterfaces; // 4:1 Number of Interfaces
UsbConfigDescriptor(int length, byte type) {
super(length, type);
+ mHierarchyLevel = 2;
}
public int getTotalLength() {
@Override
public int parseRawDescriptors(ByteStream stream) {
- mTotalLength = stream.unpackUsbWord();
+ mTotalLength = stream.unpackUsbShort();
mNumInterfaces = stream.getByte();
mConfigValue = stream.getByte();
mConfigIndex = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Config # " + getConfigValue());
+ canvas.writeListItem(getNumInterfaces() + " Interfaces.");
+ canvas.writeListItem("Attributes: " + ReportCanvas.getHexString(getAttribs()));
+ canvas.closeList();
+ }
}
import android.hardware.usb.UsbDeviceConnection;
import android.util.Log;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.Reporting;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/*
* Some notes about UsbDescriptor and its subclasses.
*
* @hide
* Common superclass for all USB Descriptors.
*/
-public abstract class UsbDescriptor {
- private static final String TAG = "Descriptor";
+public abstract class UsbDescriptor implements Reporting {
+ private static final String TAG = "UsbDescriptor";
+
+ protected int mHierarchyLevel;
protected final int mLength; // 0:1 bLength Number Size of the Descriptor in Bytes (18 bytes)
// we store this as an int because Java bytes are SIGNED.
public static final int STATUS_PARSED_OK = 1;
public static final int STATUS_PARSED_UNDERRUN = 2;
public static final int STATUS_PARSED_OVERRUN = 3;
+ public static final int STATUS_PARSE_EXCEPTION = 4;
+
private int mStatus = STATUS_UNPARSED;
private static String[] sStatusStrings = {
"UNPARSED", "PARSED - OK", "PARSED - UNDERRUN", "PARSED - OVERRUN"};
+ private int mOverUnderRunCount;
+
// Descriptor Type IDs
public static final byte DESCRIPTORTYPE_DEVICE = 0x01; // 1
public static final byte DESCRIPTORTYPE_CONFIG = 0x02; // 2
mStatus = status;
}
+ public int getOverUnderRunCount() {
+ return mOverUnderRunCount;
+ }
+
public String getStatusString() {
return sStatusStrings[mStatus];
}
// Too cold...
stream.advance(mLength - bytesRead);
mStatus = STATUS_PARSED_UNDERRUN;
+ mOverUnderRunCount = mLength - bytesRead;
Log.w(TAG, "UNDERRUN t:0x" + Integer.toHexString(mType)
- + " r:" + bytesRead + " < l:" + mLength);
+ + " r: " + bytesRead + " < l: " + mLength);
} else if (bytesRead > mLength) {
// Too hot...
stream.reverse(bytesRead - mLength);
mStatus = STATUS_PARSED_OVERRUN;
+ mOverUnderRunCount = bytesRead - mLength;
Log.w(TAG, "OVERRRUN t:0x" + Integer.toHexString(mType)
- + " r:" + bytesRead + " > l:" + mLength);
+ + " r: " + bytesRead + " > l: " + mLength);
} else {
// Just right!
mStatus = STATUS_PARSED_OK;
}
return usbStr;
}
+
+ private void reportParseStatus(ReportCanvas canvas) {
+ int status = getStatus();
+ switch (status) {
+ case UsbDescriptor.STATUS_PARSED_OK:
+ break; // no need to report
+
+ case UsbDescriptor.STATUS_UNPARSED:
+ case UsbDescriptor.STATUS_PARSED_UNDERRUN:
+ case UsbDescriptor.STATUS_PARSED_OVERRUN:
+ canvas.writeParagraph("status: " + getStatusString()
+ + " [" + getOverUnderRunCount() + "]", true);
+ break;
+ }
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ String descTypeStr = UsbStrings.getDescriptorName(getType());
+ String text = descTypeStr + ": " + ReportCanvas.getHexString(getType())
+ + " Len: " + getLength();
+ if (mHierarchyLevel != 0) {
+ canvas.writeHeader(mHierarchyLevel, text);
+ } else {
+ canvas.writeParagraph(text, false);
+ }
+
+ if (getStatus() != STATUS_PARSED_OK) {
+ reportParseStatus(canvas);
+ }
+ }
+
+ @Override
+ public void shortReport(ReportCanvas canvas) {
+ String descTypeStr = UsbStrings.getDescriptorName(getType());
+ String text = descTypeStr + ": " + ReportCanvas.getHexString(getType())
+ + " Len: " + getLength();
+ canvas.writeParagraph(text, false);
+ }
}
* @hide
* Class for parsing a binary stream of USB Descriptors.
*/
-public class UsbDescriptorParser {
- private static final String TAG = "DescriptorParser";
+public final class UsbDescriptorParser {
+ private static final String TAG = "UsbDescriptorParser";
// Descriptor Objects
private ArrayList<UsbDescriptor> mDescriptors = new ArrayList<UsbDescriptor>();
private UsbDeviceDescriptor mDeviceDescriptor;
private UsbInterfaceDescriptor mCurInterfaceDescriptor;
+ // The AudioClass spec implemented by the AudioClass Interfaces
+ // This may well be different than the overall USB Spec.
+ // Obtained from the first AudioClass Header descriptor.
+ private int mACInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0;
+
public UsbDescriptorParser() {}
/**
+ * @return the USB Spec value associated with the Device descriptor for the
+ * descriptors stream being parsed.
+ *
+ * @throws IllegalArgumentException
+ */
+ public int getUsbSpec() {
+ if (mDeviceDescriptor != null) {
+ return mDeviceDescriptor.getSpec();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public void setACInterfaceSpec(int spec) {
+ mACInterfacesSpec = spec;
+ }
+
+ public int getACInterfaceSpec() {
+ return mACInterfacesSpec;
+ }
+ /**
* The probability (as returned by getHeadsetProbability() at which we conclude
* the peripheral is a headset.
*/
private UsbDescriptor allocDescriptor(ByteStream stream) {
stream.resetReadCount();
- int length = (int) stream.getByte() & 0x000000FF;
+ int length = stream.getUnsignedByte();
byte type = stream.getByte();
UsbDescriptor descriptor = null;
if (descriptor == null) {
// Unknown Descriptor
- Log.i(TAG, "Unknown Descriptor len:" + length + " type:0x"
+ Log.i(TAG, "Unknown Descriptor len: " + length + " type:0x"
+ Integer.toHexString(type));
descriptor = new UsbUnknown(length, type);
}
try {
descriptor.parseRawDescriptors(stream);
- // Its OK to add the invalid descriptor as the postParse()
- // routine will mark it as invalid.
- mDescriptors.add(descriptor);
-
// Clean up
descriptor.postParse(stream);
} catch (Exception ex) {
Log.e(TAG, "Exception parsing USB descriptors.", ex);
+
+ // Clean up
+ descriptor.setStatus(UsbDescriptor.STATUS_PARSE_EXCEPTION);
+ } finally {
+ mDescriptors.add(descriptor);
}
}
}
list.add(descriptor);
}
} else {
- Log.w(TAG, "Unrecognized Interface l:" + descriptor.getLength()
+ Log.w(TAG, "Unrecognized Interface l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
list.add(descriptor);
}
} else {
- Log.w(TAG, "Unrecognized Audio Interface l:" + descriptor.getLength()
+ Log.w(TAG, "Unrecognized Audio Interface l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
return true;
}
} else {
- Log.w(TAG, "Undefined Audio Class Interface l:" + descriptor.getLength()
+ Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL,
UsbACInterface.AUDIO_AUDIOCONTROL);
for (UsbDescriptor descriptor : acDescriptors) {
- if (descriptor instanceof UsbACInputTerminal) {
- UsbACInputTerminal inDescr = (UsbACInputTerminal) descriptor;
+ if (descriptor instanceof UsbACTerminal) {
+ UsbACTerminal inDescr = (UsbACTerminal) descriptor;
if (inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_IN_MIC
|| inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET
|| inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED
break;
}
} else {
- Log.w(TAG, "Undefined Audio Input terminal l:" + descriptor.getLength()
+ Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
UsbACInterface.AUDIO_AUDIOCONTROL);
for (UsbDescriptor descriptor : acDescriptors) {
- if (descriptor instanceof UsbACOutputTerminal) {
- UsbACOutputTerminal outDescr = (UsbACOutputTerminal) descriptor;
+ if (descriptor instanceof UsbACTerminal) {
+ UsbACTerminal outDescr = (UsbACTerminal) descriptor;
if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER
|| outDescr.getTerminalType()
== UsbTerminalTypes.TERMINAL_OUT_HEADPHONES
break;
}
} else {
- Log.w(TAG, "Undefined Audio Output terminal l:" + descriptor.getLength()
+ Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
* to count on the peripheral being a headset.
*/
public boolean isInputHeadset() {
+ // TEMP
+ Log.i(TAG, "---- isInputHeadset() prob:" + (getInputHeadsetProbability() * 100f) + "%");
return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER;
}
getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
UsbACInterface.AUDIO_AUDIOCONTROL);
for (UsbDescriptor descriptor : acDescriptors) {
- if (descriptor instanceof UsbACOutputTerminal) {
- UsbACOutputTerminal outDescr = (UsbACOutputTerminal) descriptor;
+ if (descriptor instanceof UsbACTerminal) {
+ UsbACTerminal outDescr = (UsbACTerminal) descriptor;
if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER
|| outDescr.getTerminalType()
== UsbTerminalTypes.TERMINAL_OUT_HEADPHONES
break;
}
} else {
- Log.w(TAG, "Undefined Audio Output terminal l:" + descriptor.getLength()
+ Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
* to count on the peripheral being a headset.
*/
public boolean isOutputHeadset() {
+ // TEMP
+ Log.i(TAG, "---- isOutputHeadset() prob:" + (getOutputHeadsetProbability() * 100f) + "%");
return getOutputHeadsetProbability() >= OUT_HEADSET_TRIGGER;
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
* A USB Device Descriptor.
* see usb11.pdf section 9.6.1
*/
-/* public */ public class UsbDeviceDescriptor extends UsbDescriptor {
- private static final String TAG = "Device";
+public final class UsbDeviceDescriptor extends UsbDescriptor {
+ private static final String TAG = "UsbDeviceDescriptor";
+
+ public static final int USBSPEC_1_0 = 0x0100;
+ public static final int USBSPEC_1_1 = 0x0110;
+ public static final int USBSPEC_2_0 = 0x0200;
private int mSpec; // 2:2 bcdUSB 2 BCD USB Specification Number - BCD
private byte mDevClass; // 4:1 class code
UsbDeviceDescriptor(int length, byte type) {
super(length, type);
+ mHierarchyLevel = 1;
}
public int getSpec() {
@Override
public int parseRawDescriptors(ByteStream stream) {
- mSpec = stream.unpackUsbWord();
+ mSpec = stream.unpackUsbShort();
mDevClass = stream.getByte();
mDevSubClass = stream.getByte();
mProtocol = stream.getByte();
mPacketSize = stream.getByte();
- mVendorID = stream.unpackUsbWord();
- mProductID = stream.unpackUsbWord();
- mDeviceRelease = stream.unpackUsbWord();
+ mVendorID = stream.unpackUsbShort();
+ mProductID = stream.unpackUsbShort();
+ mDeviceRelease = stream.unpackUsbShort();
mMfgIndex = stream.getByte();
mProductIndex = stream.getByte();
mSerialNum = stream.getByte();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+
+ int spec = getSpec();
+ canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(spec));
+
+ byte devClass = getDevClass();
+ String classStr = UsbStrings.getClassName(devClass);
+ byte devSubClass = getDevSubClass();
+ String subClasStr = UsbStrings.getClassName(devSubClass);
+ canvas.writeListItem("Class " + devClass + ": " + classStr + " Subclass"
+ + devSubClass + ": " + subClasStr);
+ canvas.writeListItem("Vendor ID: " + getVendorID()
+ + " Product ID: " + getProductID()
+ + " Product Release: " + ReportCanvas.getBCDString(getDeviceRelease()));
+
+ byte mfgIndex = getMfgIndex();
+ String manufacturer =
+ UsbDescriptor.getUsbDescriptorString(canvas.getConnection(), mfgIndex);
+ byte productIndex = getProductIndex();
+ String product =
+ UsbDescriptor.getUsbDescriptorString(canvas.getConnection(), productIndex);
+
+ canvas.writeListItem("Manufacturer " + mfgIndex + ": " + manufacturer
+ + " Product " + productIndex + ": " + product);
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* A Usb Endpoint Descriptor.
* see usb11.pdf section 9.6.4
*/
public class UsbEndpointDescriptor extends UsbDescriptor {
- private static final String TAG = "EndPoint";
+ private static final String TAG = "UsbEndpointDescriptor";
- public static final byte MASK_ENDPOINT_ADDRESS = 0b0001111;
- public static final byte MASK_ENDPOINT_DIRECTION = (byte) 0b10000000;
- public static final byte DIRECTION_OUTPUT = 0x00;
- public static final byte DIRECTION_INPUT = (byte) 0x80;
+ public static final byte MASK_ENDPOINT_ADDRESS = 0b0001111;
+ public static final byte MASK_ENDPOINT_DIRECTION = (byte) 0b10000000;
+ public static final byte DIRECTION_OUTPUT = 0x00;
+ public static final byte DIRECTION_INPUT = (byte) 0x80;
public static final byte MASK_ATTRIBS_TRANSTYPE = 0b00000011;
- public static final byte TRANSTYPE_CONTROL = 0x00;
- public static final byte TRANSTYPE_ISO = 0x01;
- public static final byte TRANSTYPE_BULK = 0x02;
- public static final byte TRANSTYPE_INTERRUPT = 0x03;
-
- public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100;
- public static final byte SYNCTYPE_NONE = 0b00000000;
- public static final byte SYNCTYPE_ASYNC = 0b00000100;
- public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000;
- public static final byte SYNCTYPE_RESERVED = 0b00001100;
-
- public static final byte MASK_ATTRIBS_USEAGE = 0b00110000;
- public static final byte USEAGE_DATA = 0b00000000;
- public static final byte USEAGE_FEEDBACK = 0b00010000;
- public static final byte USEAGE_EXPLICIT = 0b00100000;
- public static final byte USEAGE_RESERVED = 0b00110000;
+ public static final byte TRANSTYPE_CONTROL = 0x00;
+ public static final byte TRANSTYPE_ISO = 0x01;
+ public static final byte TRANSTYPE_BULK = 0x02;
+ public static final byte TRANSTYPE_INTERRUPT = 0x03;
+
+ public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100;
+ public static final byte SYNCTYPE_NONE = 0b00000000;
+ public static final byte SYNCTYPE_ASYNC = 0b00000100;
+ public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000;
+ public static final byte SYNCTYPE_RESERVED = 0b00001100;
+
+ public static final byte MASK_ATTRIBS_USEAGE = 0b00110000;
+ public static final byte USEAGE_DATA = 0b00000000;
+ public static final byte USEAGE_FEEDBACK = 0b00010000;
+ public static final byte USEAGE_EXPLICIT = 0b00100000;
+ public static final byte USEAGE_RESERVED = 0b00110000;
private byte mEndpointAddress; // 2:1 Endpoint Address
// Bits 0..3b Endpoint Number.
public UsbEndpointDescriptor(int length, byte type) {
super(length, type);
+ mHierarchyLevel = 4;
}
public byte getEndpointAddress() {
public int parseRawDescriptors(ByteStream stream) {
mEndpointAddress = stream.getByte();
mAttributes = stream.getByte();
- mPacketSize = stream.unpackUsbWord();
+ mPacketSize = stream.unpackUsbShort();
mInterval = stream.getByte();
if (mLength == 9) {
mRefresh = stream.getByte();
}
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+
+ byte address = getEndpointAddress();
+ canvas.writeListItem("Address: "
+ + ReportCanvas.getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS)
+ + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION)
+ == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]"));
+
+ byte attributes = getAttributes();
+ canvas.openListItem();
+ canvas.write("Attributes: " + ReportCanvas.getHexString(attributes) + " ");
+ switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) {
+ case UsbEndpointDescriptor.TRANSTYPE_CONTROL:
+ canvas.write("Control");
+ break;
+ case UsbEndpointDescriptor.TRANSTYPE_ISO:
+ canvas.write("Iso");
+ break;
+ case UsbEndpointDescriptor.TRANSTYPE_BULK:
+ canvas.write("Bulk");
+ break;
+ case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT:
+ canvas.write("Interrupt");
+ break;
+ }
+ canvas.closeListItem();
+
+ // These flags are only relevant for ISO transfer type
+ if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE)
+ == UsbEndpointDescriptor.TRANSTYPE_ISO) {
+ canvas.openListItem();
+ canvas.write("Aync: ");
+ switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) {
+ case UsbEndpointDescriptor.SYNCTYPE_NONE:
+ canvas.write("NONE");
+ break;
+ case UsbEndpointDescriptor.SYNCTYPE_ASYNC:
+ canvas.write("ASYNC");
+ break;
+ case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC:
+ canvas.write("ADAPTIVE ASYNC");
+ break;
+ }
+ canvas.closeListItem();
+
+ canvas.openListItem();
+ canvas.write("Useage: ");
+ switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) {
+ case UsbEndpointDescriptor.USEAGE_DATA:
+ canvas.write("DATA");
+ break;
+ case UsbEndpointDescriptor.USEAGE_FEEDBACK:
+ canvas.write("FEEDBACK");
+ break;
+ case UsbEndpointDescriptor.USEAGE_EXPLICIT:
+ canvas.write("EXPLICIT FEEDBACK");
+ break;
+ case UsbEndpointDescriptor.USEAGE_RESERVED:
+ canvas.write("RESERVED");
+ break;
+ }
+ canvas.closeListItem();
+ }
+ canvas.writeListItem("Package Size: " + getPacketSize());
+ canvas.writeListItem("Interval: " + getInterval());
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* A USB HID (Human Interface Descriptor).
* see HID1_11.pdf - 6.2.1
*/
-public class UsbHIDDescriptor extends UsbDescriptor {
- private static final String TAG = "HID";
+public final class UsbHIDDescriptor extends UsbDescriptor {
+ private static final String TAG = "UsbHIDDescriptor";
private int mRelease; // 2:2 the HID Class Specification release.
private byte mCountryCode; // 4:1 country code of the localized hardware.
public UsbHIDDescriptor(int length, byte type) {
super(length, type);
+ mHierarchyLevel = 3;
}
public int getRelease() {
@Override
public int parseRawDescriptors(ByteStream stream) {
- mRelease = stream.unpackUsbWord();
+ mRelease = stream.unpackUsbShort();
mCountryCode = stream.getByte();
mNumDescriptors = stream.getByte();
mDescriptorType = stream.getByte();
- mDescriptorLen = stream.unpackUsbWord();
+ mDescriptorLen = stream.unpackUsbShort();
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.openList();
+ canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(getRelease()));
+ canvas.writeListItem("Type: " + ReportCanvas.getBCDString(getDescriptorType()));
+ canvas.writeListItem("" + getNumDescriptors() + " Descriptors Len: "
+ + getDescriptorLen());
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+// import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* A USB Interface Association Descriptor.
* found this one here: http://www.usb.org/developers/docs/whitepapers/iadclasscode_r10.pdf
* also: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540054(v=vs.85).aspx
*/
-public class UsbInterfaceAssoc extends UsbDescriptor {
- private static final String TAG = "InterfaceAssoc";
+public final class UsbInterfaceAssoc extends UsbDescriptor {
+ private static final String TAG = "UsbInterfaceAssoc";
private byte mFirstInterface;
private byte mInterfaceCount;
return mLength;
}
+
+ // TODO - Report fields
+// @Override
+// public void report(ReportCanvas canvas) {
+// super.report(canvas);
+//
+// }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.UsbStrings;
+
/**
* @hide
* A common super-class for all USB Interface Descritor subtypes.
* see usb11.pdf section 9.6.3
*/
public class UsbInterfaceDescriptor extends UsbDescriptor {
- private static final String TAG = "Interface";
+ private static final String TAG = "UsbInterfaceDescriptor";
protected byte mInterfaceNumber; // 2:1 Number of Interface
protected byte mAlternateSetting; // 3:1 Value used to select alternative setting
UsbInterfaceDescriptor(int length, byte type) {
super(length, type);
+ mHierarchyLevel = 3;
}
@Override
public byte getDescrIndex() {
return mDescrIndex;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ byte usbClass = getUsbClass();
+ byte usbSubclass = getUsbSubclass();
+ byte protocol = getProtocol();
+ String className = UsbStrings.getClassName(usbClass);
+ String subclassName = "";
+ if (usbClass == UsbDescriptor.CLASSID_AUDIO) {
+ subclassName = UsbStrings.getAudioSubclassName(usbSubclass);
+ }
+
+ canvas.openList();
+ canvas.writeListItem("Interface #" + getInterfaceNumber());
+ canvas.writeListItem("Class: " + ReportCanvas.getHexString(usbClass) + ": " + className);
+ canvas.writeListItem("Subclass: "
+ + ReportCanvas.getHexString(usbSubclass) + ": " + subclassName);
+ canvas.writeListItem("Protocol: " + protocol + ": " + ReportCanvas.getHexString(protocol));
+ canvas.writeListItem("Endpoints: " + getNumEndpoints());
+ canvas.closeList();
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Midi Streaming Interface.
* see midi10.pdf section 6.1.2.1
*/
-public class UsbMSMidiHeader extends UsbACInterface {
- private static final String TAG = "MSMidiHeader";
+public final class UsbMSMidiHeader extends UsbACInterface {
+ private static final String TAG = "UsbMSMidiHeader";
public UsbMSMidiHeader(int length, byte type, byte subtype, byte subclass) {
super(length, type, subtype, subclass);
stream.advance(mLength - stream.getReadCount());
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.writeHeader(3, "MS Midi Header: " + ReportCanvas.getHexString(getType())
+ + " SubType: " + ReportCanvas.getHexString(getSubclass())
+ + " Length: " + getLength());
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Midi Input Jack Interface.
* see midi10.pdf section B.4.3
*/
-public class UsbMSMidiInputJack extends UsbACInterface {
- private static final String TAG = "MSMidiInputJack";
+public final class UsbMSMidiInputJack extends UsbACInterface {
+ private static final String TAG = "UsbMSMidiInputJack";
UsbMSMidiInputJack(int length, byte type, byte subtype, byte subclass) {
super(length, type, subtype, subclass);
stream.advance(mLength - stream.getReadCount());
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.writeHeader(3, "MS Midi Input Jack: " + ReportCanvas.getHexString(getType())
+ + " SubType: " + ReportCanvas.getHexString(getSubclass())
+ + " Length: " + getLength());
+ }
}
*/
package com.android.server.usb.descriptors;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
/**
* @hide
* An audio class-specific Midi Output Jack Interface.
* see midi10.pdf section B.4.4
*/
-public class UsbMSMidiOutputJack extends UsbACInterface {
- private static final String TAG = "MSMidiOutputJack";
+public final class UsbMSMidiOutputJack extends UsbACInterface {
+ private static final String TAG = "UsbMSMidiOutputJack";
public UsbMSMidiOutputJack(int length, byte type, byte subtype, byte subclass) {
super(length, type, subtype, subclass);
stream.advance(mLength - stream.getReadCount());
return mLength;
}
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ super.report(canvas);
+
+ canvas.writeHeader(3, "MS Midi Output Jack: " + ReportCanvas.getHexString(getType())
+ + " SubType: " + ReportCanvas.getHexString(getSubclass())
+ + " Length: " + getLength());
+ }
}
* A class for decoding information in Terminal Descriptors.
* see termt10.pdf
*/
-public class UsbTerminalTypes {
- private static final String TAG = "TerminalTypes";
+public final class UsbTerminalTypes {
+ private static final String TAG = "UsbTerminalTypes";
// USB
public static final int TERMINAL_USB_STREAMING = 0x0101;
* @hide
* A holder for any unrecognized descriptor encountered in the descriptor stream.
*/
-public class UsbUnknown extends UsbDescriptor {
- static final String TAG = "Unknown";
+public final class UsbUnknown extends UsbDescriptor {
+ static final String TAG = "UsbUnknown";
public UsbUnknown(int length, byte type) {
super(length, type);
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.report;
+
+import android.hardware.usb.UsbDeviceConnection;
+
+/**
+ * @hide
+ * A concrete implementation of ReportCanvas class which generates HTML.
+ */
+public final class HTMLReportCanvas extends ReportCanvas {
+ private static final String TAG = "HTMLReportCanvas";
+
+ private final StringBuilder mStringBuilder;
+
+ /**
+ * Constructor. Connects HTML output to the provided StringBuilder.
+ * @param connection The USB connection object used to retrieve strings
+ * from the USB device.
+ * @param stringBuilder Generated output gets written into this object.
+ */
+ public HTMLReportCanvas(UsbDeviceConnection connection, StringBuilder stringBuilder) {
+ super(connection);
+
+ mStringBuilder = stringBuilder;
+ }
+
+ @Override
+ public void write(String text) {
+ mStringBuilder.append(text);
+ }
+
+ @Override
+ public void openHeader(int level) {
+ mStringBuilder.append("<h").append(level).append('>');
+ }
+
+ @Override
+ public void closeHeader(int level) {
+ mStringBuilder.append("</h").append(level).append('>');
+ }
+
+ // we can be cleverer (more clever?) with styles, but this will do for now.
+ @Override
+ public void openParagraph(boolean emphasis) {
+ if (emphasis) {
+ mStringBuilder.append("<p style=\"color:red\">");
+ } else {
+ mStringBuilder.append("<p>");
+ }
+ }
+
+ @Override
+ public void closeParagraph() {
+ mStringBuilder.append("</p>");
+ }
+
+ @Override
+ public void writeParagraph(String text, boolean inRed) {
+ openParagraph(inRed);
+ mStringBuilder.append(text);
+ closeParagraph();
+ }
+
+ @Override
+ public void openList() {
+ mStringBuilder.append("<ul>");
+ }
+
+ @Override
+ public void closeList() {
+ mStringBuilder.append("</ul>");
+ }
+
+ @Override
+ public void openListItem() {
+ mStringBuilder.append("<li>");
+ }
+
+ @Override
+ public void closeListItem() {
+ mStringBuilder.append("</li>");
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) 2017 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 com.android.server.usb.descriptors.report;
-
-import android.hardware.usb.UsbDeviceConnection;
-
-import com.android.server.usb.descriptors.UsbACAudioControlEndpoint;
-import com.android.server.usb.descriptors.UsbACAudioStreamEndpoint;
-import com.android.server.usb.descriptors.UsbACFeatureUnit;
-import com.android.server.usb.descriptors.UsbACHeader;
-import com.android.server.usb.descriptors.UsbACInputTerminal;
-import com.android.server.usb.descriptors.UsbACInterface;
-import com.android.server.usb.descriptors.UsbACMidiEndpoint;
-import com.android.server.usb.descriptors.UsbACMixerUnit;
-import com.android.server.usb.descriptors.UsbACOutputTerminal;
-import com.android.server.usb.descriptors.UsbACSelectorUnit;
-import com.android.server.usb.descriptors.UsbACTerminal;
-import com.android.server.usb.descriptors.UsbASFormat;
-import com.android.server.usb.descriptors.UsbASFormatI;
-import com.android.server.usb.descriptors.UsbASFormatII;
-import com.android.server.usb.descriptors.UsbASGeneral;
-import com.android.server.usb.descriptors.UsbConfigDescriptor;
-import com.android.server.usb.descriptors.UsbDescriptor;
-import com.android.server.usb.descriptors.UsbDeviceDescriptor;
-import com.android.server.usb.descriptors.UsbEndpointDescriptor;
-import com.android.server.usb.descriptors.UsbHIDDescriptor;
-import com.android.server.usb.descriptors.UsbInterfaceAssoc;
-import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
-import com.android.server.usb.descriptors.UsbMSMidiHeader;
-import com.android.server.usb.descriptors.UsbMSMidiInputJack;
-import com.android.server.usb.descriptors.UsbMSMidiOutputJack;
-import com.android.server.usb.descriptors.UsbUnknown;
-
-/**
- * Implements the Reporter inteface to provide HTML reporting for UsbDescriptor subclasses.
- */
-public class HTMLReporter implements Reporter {
- private final StringBuilder mStringBuilder;
- private final UsbDeviceConnection mConnection;
-
- public HTMLReporter(StringBuilder stringBuilder, UsbDeviceConnection connection) {
- mStringBuilder = stringBuilder;
- mConnection = connection;
- }
-
- /*
- * HTML Helpers
- */
- private void writeHeader(int level, String text) {
- mStringBuilder
- .append("<h").append(level).append('>')
- .append(text)
- .append("</h").append(level).append('>');
- }
-
- private void openParagraph() {
- mStringBuilder.append("<p>");
- }
-
- private void closeParagraph() {
- mStringBuilder.append("</p>");
- }
-
- private void writeParagraph(String text) {
- openParagraph();
- mStringBuilder.append(text);
- closeParagraph();
- }
-
- private void openList() {
- mStringBuilder.append("<ul>");
- }
-
- private void closeList() {
- mStringBuilder.append("</ul>");
- }
-
- private void openListItem() {
- mStringBuilder.append("<li>");
- }
-
- private void closeListItem() {
- mStringBuilder.append("</li>");
- }
-
- private void writeListItem(String text) {
- openListItem();
- mStringBuilder.append(text);
- closeListItem();
- }
-
- /*
- * Data Formating Helpers
- */
- private static String getHexString(byte value) {
- return "0x" + Integer.toHexString(((int) value) & 0xFF).toUpperCase();
- }
-
- private static String getBCDString(int value) {
- int major = value >> 8;
- int minor = (value >> 4) & 0x0F;
- int subminor = value & 0x0F;
-
- return "" + major + "." + minor + subminor;
- }
-
- private static String getHexString(int value) {
- int intValue = value & 0xFFFF;
- return "0x" + Integer.toHexString(intValue).toUpperCase();
- }
-
- private void dumpHexArray(byte[] rawData, StringBuilder builder) {
- if (rawData != null) {
- // Assume the type and Length and perhaps sub-type have been displayed
- openParagraph();
- for (int index = 0; index < rawData.length; index++) {
- builder.append(getHexString(rawData[index]) + " ");
- }
- closeParagraph();
- }
- }
-
- /**
- * Decode ACTUAL UsbDescriptor sub classes and call type-specific report methods.
- */
- @Override
- public void report(UsbDescriptor descriptor) {
- if (descriptor instanceof UsbDeviceDescriptor) {
- tsReport((UsbDeviceDescriptor) descriptor);
- } else if (descriptor instanceof UsbConfigDescriptor) {
- tsReport((UsbConfigDescriptor) descriptor);
- } else if (descriptor instanceof UsbInterfaceDescriptor) {
- tsReport((UsbInterfaceDescriptor) descriptor);
- } else if (descriptor instanceof UsbEndpointDescriptor) {
- tsReport((UsbEndpointDescriptor) descriptor);
- } else if (descriptor instanceof UsbHIDDescriptor) {
- tsReport((UsbHIDDescriptor) descriptor);
- } else if (descriptor instanceof UsbACAudioControlEndpoint) {
- tsReport((UsbACAudioControlEndpoint) descriptor);
- } else if (descriptor instanceof UsbACAudioStreamEndpoint) {
- tsReport((UsbACAudioStreamEndpoint) descriptor);
- } else if (descriptor instanceof UsbACHeader) {
- tsReport((UsbACHeader) descriptor);
- } else if (descriptor instanceof UsbACFeatureUnit) {
- tsReport((UsbACFeatureUnit) descriptor);
- } else if (descriptor instanceof UsbACInputTerminal) {
- tsReport((UsbACInputTerminal) descriptor);
- } else if (descriptor instanceof UsbACOutputTerminal) {
- tsReport((UsbACOutputTerminal) descriptor);
- } else if (descriptor instanceof UsbACMidiEndpoint) {
- tsReport((UsbACMidiEndpoint) descriptor);
- } else if (descriptor instanceof UsbACMixerUnit) {
- tsReport((UsbACMixerUnit) descriptor);
- } else if (descriptor instanceof UsbACSelectorUnit) {
- tsReport((UsbACSelectorUnit) descriptor);
- } else if (descriptor instanceof UsbASFormatI) {
- tsReport((UsbASFormatI) descriptor);
- } else if (descriptor instanceof UsbASFormatII) {
- tsReport((UsbASFormatII) descriptor);
- } else if (descriptor instanceof UsbASFormat) {
- tsReport((UsbASFormat) descriptor);
- } else if (descriptor instanceof UsbASGeneral) {
- tsReport((UsbASGeneral) descriptor);
- } else if (descriptor instanceof UsbInterfaceAssoc) {
- tsReport((UsbInterfaceAssoc) descriptor);
- } else if (descriptor instanceof UsbMSMidiHeader) {
- tsReport((UsbMSMidiHeader) descriptor);
- } else if (descriptor instanceof UsbMSMidiInputJack) {
- tsReport((UsbMSMidiInputJack) descriptor);
- } else if (descriptor instanceof UsbMSMidiOutputJack) {
- tsReport((UsbMSMidiOutputJack) descriptor);
- } else if (descriptor instanceof UsbUnknown) {
- tsReport((UsbUnknown) descriptor);
- } else if (descriptor instanceof UsbACInterface) {
- tsReport((UsbACInterface) descriptor);
- } else if (descriptor instanceof UsbDescriptor) {
- tsReport((UsbDescriptor) descriptor);
- }
- }
-
- //
- // Type-specific report() implementations
- //
- private void tsReport(UsbDescriptor descriptor) {
- int length = descriptor.getLength();
- byte type = descriptor.getType();
- int status = descriptor.getStatus();
-
- String descTypeStr = UsbStrings.getDescriptorName(type);
- writeParagraph(descTypeStr + ":" + type + " l:" + length + " s:" + status);
- }
-
- private void tsReport(UsbDeviceDescriptor descriptor) {
- writeHeader(1, "Device len:" + descriptor.getLength());
- openList();
-
- int spec = descriptor.getSpec();
- writeListItem("spec:" + getBCDString(spec));
-
- byte devClass = descriptor.getDevClass();
- String classStr = UsbStrings.getClassName(devClass);
- byte devSubClass = descriptor.getDevSubClass();
- String subClasStr = UsbStrings.getClassName(devSubClass);
- writeListItem("class " + devClass + ":" + classStr + " subclass"
- + devSubClass + ":" + subClasStr);
- writeListItem("vendorID:" + descriptor.getVendorID()
- + " prodID:" + descriptor.getProductID()
- + " prodRel:" + getBCDString(descriptor.getDeviceRelease()));
-
- byte mfgIndex = descriptor.getMfgIndex();
- String manufacturer = UsbDescriptor.getUsbDescriptorString(mConnection, mfgIndex);
- byte productIndex = descriptor.getProductIndex();
- String product = UsbDescriptor.getUsbDescriptorString(mConnection, productIndex);
-
- writeListItem("mfg " + mfgIndex + ":" + manufacturer
- + " prod " + productIndex + ":" + product);
- closeList();
- }
-
- private void tsReport(UsbConfigDescriptor descriptor) {
- writeHeader(2, "Config #" + descriptor.getConfigValue()
- + " len:" + descriptor.getLength());
-
- openList();
- writeListItem(descriptor.getNumInterfaces() + " interfaces.");
- writeListItem("attribs:" + getHexString(descriptor.getAttribs()));
- closeList();
- }
-
- private void tsReport(UsbInterfaceDescriptor descriptor) {
- byte usbClass = descriptor.getUsbClass();
- byte usbSubclass = descriptor.getUsbSubclass();
- String descr = UsbStrings.getDescriptorName(descriptor.getType());
- String className = UsbStrings.getClassName(usbClass);
- String subclassName = "";
- if (usbClass == UsbDescriptor.CLASSID_AUDIO) {
- subclassName = UsbStrings.getAudioSubclassName(usbSubclass);
- }
-
- writeHeader(2, descr + " #" + descriptor.getInterfaceNumber()
- + " len:" + descriptor.getLength());
- String descrStr =
- UsbDescriptor.getUsbDescriptorString(mConnection, descriptor.getDescrIndex());
- if (descrStr.length() > 0) {
- mStringBuilder.append("<br>" + descrStr);
- }
- openList();
- writeListItem("class " + getHexString(usbClass) + ":" + className
- + " subclass " + getHexString(usbSubclass) + ":" + subclassName);
- writeListItem("" + descriptor.getNumEndpoints() + " endpoints");
- closeList();
- }
-
- private void tsReport(UsbEndpointDescriptor descriptor) {
- writeHeader(3, "Endpoint " + getHexString(descriptor.getType())
- + " len:" + descriptor.getLength());
- openList();
-
- byte address = descriptor.getEndpointAddress();
- writeListItem("address:"
- + getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS)
- + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION)
- == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]"));
-
- byte attributes = descriptor.getAttributes();
- openListItem();
- mStringBuilder.append("attribs:" + getHexString(attributes) + " ");
- switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) {
- case UsbEndpointDescriptor.TRANSTYPE_CONTROL:
- mStringBuilder.append("Control");
- break;
- case UsbEndpointDescriptor.TRANSTYPE_ISO:
- mStringBuilder.append("Iso");
- break;
- case UsbEndpointDescriptor.TRANSTYPE_BULK:
- mStringBuilder.append("Bulk");
- break;
- case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT:
- mStringBuilder.append("Interrupt");
- break;
- }
- closeListItem();
-
- // These flags are only relevant for ISO transfer type
- if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE)
- == UsbEndpointDescriptor.TRANSTYPE_ISO) {
- openListItem();
- mStringBuilder.append("sync:");
- switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) {
- case UsbEndpointDescriptor.SYNCTYPE_NONE:
- mStringBuilder.append("NONE");
- break;
- case UsbEndpointDescriptor.SYNCTYPE_ASYNC:
- mStringBuilder.append("ASYNC");
- break;
- case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC:
- mStringBuilder.append("ADAPTIVE ASYNC");
- break;
- }
- closeListItem();
-
- openListItem();
- mStringBuilder.append("useage:");
- switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) {
- case UsbEndpointDescriptor.USEAGE_DATA:
- mStringBuilder.append("DATA");
- break;
- case UsbEndpointDescriptor.USEAGE_FEEDBACK:
- mStringBuilder.append("FEEDBACK");
- break;
- case UsbEndpointDescriptor.USEAGE_EXPLICIT:
- mStringBuilder.append("EXPLICIT FEEDBACK");
- break;
- case UsbEndpointDescriptor.USEAGE_RESERVED:
- mStringBuilder.append("RESERVED");
- break;
- }
- closeListItem();
- }
- writeListItem("package size:" + descriptor.getPacketSize());
- writeListItem("interval:" + descriptor.getInterval());
- closeList();
- }
-
- private void tsReport(UsbHIDDescriptor descriptor) {
- String descr = UsbStrings.getDescriptorName(descriptor.getType());
- writeHeader(2, descr + " len:" + descriptor.getLength());
- openList();
- writeListItem("spec:" + getBCDString(descriptor.getRelease()));
- writeListItem("type:" + getBCDString(descriptor.getDescriptorType()));
- writeListItem("descriptor.getNumDescriptors() descriptors len:"
- + descriptor.getDescriptorLen());
- closeList();
- }
-
- private void tsReport(UsbACAudioControlEndpoint descriptor) {
- writeHeader(3, "AC Audio Control Endpoint:" + getHexString(descriptor.getType())
- + " length:" + descriptor.getLength());
- }
-
- private void tsReport(UsbACAudioStreamEndpoint descriptor) {
- writeHeader(3, "AC Audio Streaming Endpoint:"
- + getHexString(descriptor.getType())
- + " length:" + descriptor.getLength());
- }
-
- private void tsReport(UsbACHeader descriptor) {
- tsReport((UsbACInterface) descriptor);
-
- openList();
- writeListItem("spec:" + getBCDString(descriptor.getADCRelease()));
- int numInterfaces = descriptor.getNumInterfaces();
- writeListItem("" + numInterfaces + " interfaces");
- if (numInterfaces > 0) {
- openListItem();
- mStringBuilder.append("[");
- byte[] interfaceNums = descriptor.getInterfaceNums();
- if (numInterfaces != 0 && interfaceNums != null) {
- for (int index = 0; index < numInterfaces; index++) {
- mStringBuilder.append("" + interfaceNums[index]);
- if (index < numInterfaces - 1) {
- mStringBuilder.append(" ");
- }
- }
- }
- mStringBuilder.append("]");
- closeListItem();
- }
- writeListItem("controls:" + getHexString(descriptor.getControls()));
- closeList();
- }
-
- private void tsReport(UsbACFeatureUnit descriptor) {
- tsReport((UsbACInterface) descriptor);
- }
-
- private void tsReport(UsbACInterface descriptor) {
- String subClassName =
- descriptor.getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
- ? "AC Control"
- : "AC Streaming";
- byte subtype = descriptor.getSubtype();
- String subTypeStr = UsbStrings.getACControlInterfaceName(subtype);
- writeHeader(4, subClassName + " - " + getHexString(subtype)
- + ":" + subTypeStr + " len:" + descriptor.getLength());
- }
-
- private void tsReport(UsbACTerminal descriptor) {
- tsReport((UsbACInterface) descriptor);
- }
-
- private void tsReport(UsbACInputTerminal descriptor) {
- tsReport((UsbACTerminal) descriptor);
-
- openList();
- writeListItem("ID:" + getHexString(descriptor.getTerminalID()));
- int terminalType = descriptor.getTerminalType();
- writeListItem("Type:<b>" + getHexString(terminalType) + ":"
- + UsbStrings.getTerminalName(terminalType) + "</b>");
- writeListItem("AssocTerminal:" + getHexString(descriptor.getAssocTerminal()));
- writeListItem("" + descriptor.getNrChannels() + " chans. config:"
- + getHexString(descriptor.getChannelConfig()));
- closeList();
- }
-
- private void tsReport(UsbACOutputTerminal descriptor) {
- tsReport((UsbACTerminal) descriptor);
-
- openList();
- writeListItem("ID:" + getHexString(descriptor.getTerminalID()));
- int terminalType = descriptor.getTerminalType();
- writeListItem("Type:<b>" + getHexString(terminalType) + ":"
- + UsbStrings.getTerminalName(terminalType) + "</b>");
- writeListItem("AssocTerminal:" + getHexString(descriptor.getAssocTerminal()));
- writeListItem("Source:" + getHexString(descriptor.getSourceID()));
- closeList();
- }
-
- private void tsReport(UsbACMidiEndpoint descriptor) {
- writeHeader(3, "AC Midi Endpoint:" + getHexString(descriptor.getType())
- + " length:" + descriptor.getLength());
- openList();
- writeListItem("" + descriptor.getNumJacks() + " jacks.");
- closeList();
- }
-
- private void tsReport(UsbACMixerUnit descriptor) {
- tsReport((UsbACInterface) descriptor);
- openList();
-
- writeListItem("Unit ID:" + getHexString(descriptor.getUnitID()));
- byte numInputs = descriptor.getNumInputs();
- byte[] inputIDs = descriptor.getInputIDs();
- openListItem();
- mStringBuilder.append("Num Inputs:" + numInputs + " [");
- for (int input = 0; input < numInputs; input++) {
- mStringBuilder.append("" + getHexString(inputIDs[input]));
- if (input < numInputs - 1) {
- mStringBuilder.append(" ");
- }
- }
- mStringBuilder.append("]");
- closeListItem();
-
- writeListItem("Num Outputs:" + descriptor.getNumOutputs());
- writeListItem("Chan Config:" + getHexString(descriptor.getChannelConfig()));
-
- byte[] controls = descriptor.getControls();
- openListItem();
- mStringBuilder.append("controls:" + controls.length + " [");
- for (int ctrl = 0; ctrl < controls.length; ctrl++) {
- mStringBuilder.append("" + controls[ctrl]);
- if (ctrl < controls.length - 1) {
- mStringBuilder.append(" ");
- }
- }
- mStringBuilder.append("]");
- closeListItem();
- closeList();
- // byte mChanNameID; // First channel name string descriptor ID
- // byte mNameID; // string descriptor ID of mixer name
- }
-
- private void tsReport(UsbACSelectorUnit descriptor) {
- tsReport((UsbACInterface) descriptor);
- }
-
- private void tsReport(UsbASFormat descriptor) {
- writeHeader(4, "AC Streaming Format "
- + (descriptor.getFormatType() == UsbASFormat.FORMAT_TYPE_I ? "I" : "II")
- + " - " + getHexString(descriptor.getSubtype()) + ":"
- + " len:" + descriptor.getLength());
- }
-
- private void tsReport(UsbASFormatI descriptor) {
- tsReport((UsbASFormat) descriptor);
- openList();
- writeListItem("chans:" + descriptor.getNumChannels());
- writeListItem("subframe size:" + descriptor.getSubframeSize());
- writeListItem("bit resolution:" + descriptor.getBitResolution());
- byte sampleFreqType = descriptor.getSampleFreqType();
- int[] sampleRates = descriptor.getSampleRates();
- writeListItem("sample freq type:" + sampleFreqType);
- if (sampleFreqType == 0) {
- openList();
- writeListItem("min:" + sampleRates[0]);
- writeListItem("max:" + sampleRates[1]);
- closeList();
- } else {
- openList();
- for (int index = 0; index < sampleFreqType; index++) {
- writeListItem("" + sampleRates[index]);
- }
- closeList();
- }
- closeList();
- }
-
- private void tsReport(UsbASFormatII descriptor) {
- tsReport((UsbASFormat) descriptor);
- openList();
- writeListItem("max bit rate:" + descriptor.getMaxBitRate());
- writeListItem("samples per frame:" + descriptor.getMaxBitRate());
- byte sampleFreqType = descriptor.getSamFreqType();
- int[] sampleRates = descriptor.getSampleRates();
- writeListItem("sample freq type:" + sampleFreqType);
- if (sampleFreqType == 0) {
- openList();
- writeListItem("min:" + sampleRates[0]);
- writeListItem("max:" + sampleRates[1]);
- closeList();
- } else {
- openList();
- for (int index = 0; index < sampleFreqType; index++) {
- writeListItem("" + sampleRates[index]);
- }
- closeList();
- }
-
- closeList();
- }
-
- private void tsReport(UsbASGeneral descriptor) {
- tsReport((UsbACInterface) descriptor);
- openList();
- int formatTag = descriptor.getFormatTag();
- writeListItem("fmt:" + UsbStrings.getAudioFormatName(formatTag) + " - "
- + getHexString(formatTag));
- closeList();
- }
-
- private void tsReport(UsbInterfaceAssoc descriptor) {
- tsReport((UsbDescriptor) descriptor);
- }
-
- private void tsReport(UsbMSMidiHeader descriptor) {
- writeHeader(3, "MS Midi Header:" + getHexString(descriptor.getType())
- + " subType:" + getHexString(descriptor.getSubclass())
- + " length:" + descriptor.getSubclass());
- }
-
- private void tsReport(UsbMSMidiInputJack descriptor) {
- writeHeader(3, "MS Midi Input Jack:" + getHexString(descriptor.getType())
- + " subType:" + getHexString(descriptor.getSubclass())
- + " length:" + descriptor.getSubclass());
- }
-
- private void tsReport(UsbMSMidiOutputJack descriptor) {
- writeHeader(3, "MS Midi Output Jack:" + getHexString(descriptor.getType())
- + " subType:" + getHexString(descriptor.getSubclass())
- + " length:" + descriptor.getSubclass());
- }
-
- private void tsReport(UsbUnknown descriptor) {
- writeParagraph("<i><b>Unknown Descriptor " + getHexString(descriptor.getType())
- + " len:" + descriptor.getLength() + "</b></i>");
- dumpHexArray(descriptor.getRawData(), mStringBuilder);
- }
-}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.report;
+
+import android.hardware.usb.UsbDeviceConnection;
+
+/**
+ * @hide
+ * Defines a class for generating report data in a variety of potential formats.
+ */
+public abstract class ReportCanvas {
+ private static final String TAG = "ReportCanvas";
+
+ private final UsbDeviceConnection mConnection;
+
+ /**
+ * Constructor.
+ * @param connection The USB connection object used to retrieve strings
+ * from the USB device.
+ */
+ public ReportCanvas(UsbDeviceConnection connection) {
+ mConnection = connection;
+ }
+
+ /**
+ * @returns the UsbDeviceConnection member (mConnection).
+ */
+ public UsbDeviceConnection getConnection() {
+ return mConnection;
+ }
+
+ /**
+ * Writes a plain string to the output.
+ */
+ public abstract void write(String text);
+
+ /**
+ * Opens a "header" formatted section in the output.
+ * @param level Specifies the logical level of the header.
+ */
+ public abstract void openHeader(int level);
+
+ /**
+ * Closes a "header" formatted section in the output.
+ * @param level Specifies the logical level of the header.
+ */
+ public abstract void closeHeader(int level);
+
+ /**
+ * Writes a "header" formatted string to the output.
+ * @param level Specifies the logical level of the header.
+ * @param text Specifies the text to display in the header.
+ */
+ public void writeHeader(int level, String text) {
+ openHeader(level);
+ write(text);
+ closeHeader(level);
+ }
+
+ /**
+ * Opens a paragraph construct in the output.
+ * @param emphasis Specifies whether the text in the paragraph should
+ * be displayed with "emphasis" formatting.
+ */
+ public abstract void openParagraph(boolean emphasis);
+
+ /**
+ * Closes a paragraph construct in the output.
+ */
+ public abstract void closeParagraph();
+
+ /**
+ * Writes a paragraph construct to the output.
+ * @param text The text to display with "paragraph" formatting.
+ * @param emphasis Specifies whether the text in the paragraph should
+ * be displayed with "emphasis" formatting.
+ */
+ public abstract void writeParagraph(String text, boolean emphasis);
+
+ /**
+ * Opens a "list" formatted section in the output.
+ */
+ public abstract void openList();
+
+ /**
+ * Closes a "list" formatted section in the output.
+ */
+ public abstract void closeList();
+
+ /**
+ * Opens a "list item" formatted section in the output.
+ */
+ public abstract void openListItem();
+
+ /**
+ * Closes a "list item" formatted section in the output.
+ */
+ public abstract void closeListItem();
+
+ /**
+ * Writes a "list item" formatted section in the output.
+ * @param text Specifies the text of the list item.
+ */
+ public void writeListItem(String text) {
+ openListItem();
+ write(text);
+ closeListItem();
+ }
+
+ /*
+ * Data Formating Helpers
+ */
+ /**
+ * Generates a hex representation of the specified byte value.
+ * @param value The value to format.
+ */
+ //TODO Look into renaming the "getHexString()" functions to be more
+ // representative of the types they handle.
+ public static String getHexString(byte value) {
+ return "0x" + Integer.toHexString(((int) value) & 0xFF).toUpperCase();
+ }
+
+ /**
+ * Generates a string representing a USB Binary-Coded Decimal value.
+ * @param valueBCD The value to format.
+ */
+ public static String getBCDString(int valueBCD) {
+ int major = (valueBCD >> 8) & 0x0F;
+ int minor = (valueBCD >> 4) & 0x0F;
+ int subminor = valueBCD & 0x0F;
+
+ return "" + major + "." + minor + subminor;
+ }
+
+ /**
+ * Generates a hex representation of the specified 16-bit integer value.
+ * @param value The value to format.
+ */
+ //TODO Look into renaming the "getHexString()" functions to be more
+ // representative of the types they handle.
+ public static String getHexString(int value) {
+ int intValue = value & 0xFFFF;
+ return "0x" + Integer.toHexString(intValue).toUpperCase();
+ }
+
+ /**
+ * Writes out the specified byte array to the provided StringBuilder.
+ * @param rawData The byte values.
+ * @param builder The StringBuilder to write text into.
+ */
+ public void dumpHexArray(byte[] rawData, StringBuilder builder) {
+ if (rawData != null) {
+ // Assume the type and Length and perhaps sub-type have been displayed
+ openParagraph(false);
+ for (int index = 0; index < rawData.length; index++) {
+ builder.append(getHexString(rawData[index]) + " ");
+ }
+ closeParagraph();
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) 2017 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 com.android.server.usb.descriptors.report;
-
-import com.android.server.usb.descriptors.UsbDescriptor;
-
-/**
- * Declares the Reporter interface to provide HTML reporting for UsbDescriptor (sub)classes.
- *
- * NOTE: It is the responsibility of the implementor of this interface to correctly
- * interpret/decode the SPECIFIC UsbDescriptor subclass (perhaps with 'instanceof') that is
- * passed and handle that in the appropriate manner. This appears to be a
- * not very object-oriented approach, and that is true. This approach DOES however move the
- * complexity and 'plumbing' of reporting into the Reporter implementation and avoids needing
- * a (trivial) type-specific call to 'report()' in each UsbDescriptor (sub)class, instead
- * having just one in the top-level UsbDescriptor class. It also removes the need to add new
- * type-specific 'report()' methods to be added to Reporter interface whenever a
- * new UsbDescriptor subclass is defined. This seems like a pretty good trade-off.
- *
- * See HTMLReporter.java in this package for an example of type decoding.
- */
-public interface Reporter {
- /**
- * Generate report for this UsbDescriptor descriptor
- */
- void report(UsbDescriptor descriptor);
-}
package com.android.server.usb.descriptors.report;
/**
- * Declares the interface for classes that provide reporting functionality.
- * (This is the double-indirection aspect of the "Visitor" pattern.
+ * @hide
*/
public interface Reporting {
/**
- * Declares the report method that UsbDescriptor subclasses call.
+ * TBD
*/
- void report(Reporter reporter);
+ void report(ReportCanvas canvas);
+
+ /**
+ * TBD
+ */
+ void shortReport(ReportCanvas canvas);
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.report;
+
+import android.hardware.usb.UsbDeviceConnection;
+
+/**
+ * @hide
+ * A concrete implementation of ReportCanvas class which generates "Plain Text" output.
+ */
+public final class TextReportCanvas extends ReportCanvas {
+ private static final String TAG = "TextReportCanvas";
+
+ private final StringBuilder mStringBuilder;
+ private int mListIndent;
+ private static final int LIST_INDENT_AMNT = 2;
+
+ /**
+ * Constructor. Connects plain-text output to the provided StringBuilder.
+ * @param connection The USB connection object used to retrieve strings
+ * from the USB device.
+ * @param stringBuilder Generated output gets written into this object.
+ */
+ public TextReportCanvas(UsbDeviceConnection connection, StringBuilder stringBuilder) {
+ super(connection);
+
+ mStringBuilder = stringBuilder;
+ }
+
+ @Override
+ public void write(String text) {
+ mStringBuilder.append(text);
+ }
+
+ @Override
+ public void openHeader(int level) {
+ mStringBuilder.append("[" + level + " - ");
+ }
+
+ @Override
+ public void closeHeader(int level) {
+ mStringBuilder.append("]\n");
+ }
+
+ @Override
+ public void openParagraph(boolean inRed) {
+ }
+
+ @Override
+ public void closeParagraph() {
+ mStringBuilder.append("\n");
+ }
+
+ @Override
+ public void writeParagraph(String text, boolean inRed) {
+ openParagraph(inRed);
+ if (inRed) {
+ mStringBuilder.append("*" + text + "*");
+ } else {
+ mStringBuilder.append(text);
+ }
+ closeParagraph();
+ }
+
+ private void writeListIndent() {
+ for (int space = 0; space < mListIndent; space++) {
+ mStringBuilder.append(" ");
+ }
+ }
+
+ @Override
+ public void openList() {
+ mListIndent += LIST_INDENT_AMNT;
+ writeListIndent();
+ mStringBuilder.append("---->\n");
+ }
+
+ @Override
+ public void closeList() {
+ writeListIndent();
+ mListIndent -= LIST_INDENT_AMNT;
+ mStringBuilder.append("<----\n");
+ }
+
+ @Override
+ public void openListItem() {
+ writeListIndent();
+ mStringBuilder.append(" - ");
+ }
+
+ @Override
+ public void closeListItem() {
+ mStringBuilder.append("\n");
+ }
+}
package com.android.server.usb.descriptors.report;
import com.android.server.usb.descriptors.UsbACInterface;
+import com.android.server.usb.descriptors.UsbASFormat;
import com.android.server.usb.descriptors.UsbDescriptor;
import com.android.server.usb.descriptors.UsbTerminalTypes;
* @hide
* A class to provide human-readable strings for various USB constants.
*/
-public class UsbStrings {
+public final class UsbStrings {
private static final String TAG = "UsbStrings";
private static HashMap<Byte, String> sDescriptorNames;
private static HashMap<Byte, String> sAudioSubclassNames;
private static HashMap<Integer, String> sAudioEncodingNames;
private static HashMap<Integer, String> sTerminalNames;
+ private static HashMap<Integer, String> sFormatNames;
private static void initDescriptorNames() {
sDescriptorNames = new HashMap<Byte, String>();
sACControlInterfaceNames.put(UsbACInterface.ACI_FEATURE_UNIT, "Feature Unit");
sACControlInterfaceNames.put(UsbACInterface.ACI_PROCESSING_UNIT, "Processing Unit");
sACControlInterfaceNames.put(UsbACInterface.ACI_EXTENSION_UNIT, "Extension Unit");
+ sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_SOURCE, "Clock Source");
+ sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_SELECTOR, "Clock Selector");
+ sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_MULTIPLIER, "Clock Multiplier");
+ sACControlInterfaceNames.put(UsbACInterface.ACI_SAMPLE_RATE_CONVERTER,
+ "Sample Rate Converter");
}
private static void initACStreamingInterfaceNames() {
? name
: "Unknown Terminal Type 0x" + Integer.toHexString(terminalType);
}
+
+ private static void initFormatNames() {
+ sFormatNames = new HashMap<Integer, String>();
+
+ sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_I, "FORMAT_TYPE_I");
+ sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_II, "FORMAT_TYPE_II");
+ sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_III, "FORMAT_TYPE_III");
+ sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_IV, "FORMAT_TYPE_IV");
+ sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_I, "EXT_FORMAT_TYPE_I");
+ sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_II, "EXT_FORMAT_TYPE_II");
+ sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_III, "EXT_FORMAT_TYPE_III");
+ }
+
+ /**
+ * Retrieves the name for the specified format (encoding) type ID.
+ */
+ public static String getFormatName(int format) {
+ String name = sFormatNames.get(format);
+ return name != null
+ ? name
+ : "Unknown Format Type 0x" + Integer.toHexString(format);
+ }
+
/**
* Initializes string tables.
*/
initAudioSubclassNames();
initAudioEncodingNames();
initTerminalNames();
+ initFormatNames();
}
/**
- * Initializes string tables.
+ * Deinitializes string tables.
*/
public static void releaseUsbStrings() {
sDescriptorNames = null;
: "Unknown Format (encoding) ID [0x" + Integer.toHexString(formatID) + ":"
+ formatID + "]";
}
+
+ /**
+ * Retrieves the name for the specified USB audio interface subclass ID.
+ */
+ public static String getACInterfaceSubclassName(byte subClassID) {
+ return subClassID == UsbDescriptor.AUDIO_AUDIOCONTROL ? "AC Control" : "AC Streaming";
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbACInterface;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * A tree node containing some sort-of Audio Class Descriptor.
+ */
+public final class UsbDescriptorsACInterfaceNode extends UsbDescriptorsTreeNode {
+ private static final String TAG = "UsbDescriptorsACInterfaceNode";
+
+ private final UsbACInterface mACInterface;
+
+ /**
+ * Constructor.
+ * @param acInterface The Audio Class Inteface object wrapped by this tree node.
+ */
+ public UsbDescriptorsACInterfaceNode(UsbACInterface acInterface) {
+ mACInterface = acInterface;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ canvas.openListItem();
+ canvas.writeParagraph("AC Interface type:0x"
+ + Integer.toHexString(mACInterface.getSubtype()), false);
+ mACInterface.report(canvas);
+ canvas.closeListItem();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbConfigDescriptor;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+import java.util.ArrayList;
+
+/**
+ * @hide
+ * Represents a configuration in the descriptors tree.
+ */
+public final class UsbDescriptorsConfigNode extends UsbDescriptorsTreeNode {
+ private static final String TAG = "UsbDescriptorsConfigNode";
+
+ private final UsbConfigDescriptor mConfigDescriptor;
+
+ private final ArrayList<UsbDescriptorsInterfaceNode> mInterfaceNodes = new ArrayList<>();
+
+ /**
+ * Constructor.
+ * @param configDescriptor The Config Descriptor object wrapped by this tree node.
+ */
+ public UsbDescriptorsConfigNode(UsbConfigDescriptor configDescriptor) {
+ mConfigDescriptor = configDescriptor;
+ }
+
+ /**
+ * Adds the inteface node logical contained in this configuration.
+ * @param interfaceNode The inteface treenode to assocate with this configuration.
+ */
+ public void addInterfaceNode(UsbDescriptorsInterfaceNode interfaceNode) {
+ mInterfaceNodes.add(interfaceNode);
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ mConfigDescriptor.report(canvas);
+
+ canvas.openList();
+
+ // Interfaces
+ for (UsbDescriptorsInterfaceNode node : mInterfaceNodes) {
+ node.report(canvas);
+ }
+
+ canvas.closeList();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbDeviceDescriptor;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+import java.util.ArrayList;
+
+/**
+ * @hide
+ * A class to contain THE device descriptor at the root of the tree.
+ */
+public final class UsbDescriptorsDeviceNode extends UsbDescriptorsTreeNode {
+ private static final String TAG = "UsbDescriptorsDeviceNode";
+
+ private final UsbDeviceDescriptor mDeviceDescriptor;
+
+ private final ArrayList<UsbDescriptorsConfigNode> mConfigNodes = new ArrayList<>();
+
+ /**
+ * Constructor.
+ * @param deviceDescriptor The Device Descriptor object wrapped by this tree node.
+ */
+ public UsbDescriptorsDeviceNode(UsbDeviceDescriptor deviceDescriptor) {
+ mDeviceDescriptor = deviceDescriptor;
+ }
+
+ /**
+ * Adds a Configuration node to the assocated device node.
+ */
+ public void addConfigDescriptorNode(UsbDescriptorsConfigNode configNode) {
+ mConfigNodes.add(configNode);
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ mDeviceDescriptor.report(canvas);
+ for (UsbDescriptorsConfigNode node : mConfigNodes) {
+ node.report(canvas);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbEndpointDescriptor;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * Represents an endpoint in the descriptors tree.
+ */
+public final class UsbDescriptorsEndpointNode extends UsbDescriptorsTreeNode {
+ private static final String TAG = "UsbDescriptorsEndpointNode";
+
+ private final UsbEndpointDescriptor mEndpointDescriptor;
+
+ /**
+ * Constructor.
+ * @param endpointDescriptor The Device Descriptor object wrapped by this tree node.
+ */
+ public UsbDescriptorsEndpointNode(UsbEndpointDescriptor endpointDescriptor) {
+ mEndpointDescriptor = endpointDescriptor;
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ mEndpointDescriptor.report(canvas);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+import java.util.ArrayList;
+
+/**
+ * @hide
+ * Represents an interface in the descriptors tree.
+ */
+public final class UsbDescriptorsInterfaceNode extends UsbDescriptorsTreeNode {
+ private static final String TAG = "UsbDescriptorsInterfaceNode";
+
+ private final UsbInterfaceDescriptor mInterfaceDescriptor;
+
+ private final ArrayList<UsbDescriptorsEndpointNode> mEndpointNodes = new ArrayList<>();
+ private final ArrayList<UsbDescriptorsACInterfaceNode> mACInterfaceNodes = new ArrayList<>();
+
+ /**
+ * Constructor.
+ * @param interfaceDescriptor The Interface Descriptor object wrapped by this tree node.
+ */
+ public UsbDescriptorsInterfaceNode(UsbInterfaceDescriptor interfaceDescriptor) {
+ mInterfaceDescriptor = interfaceDescriptor;
+ }
+
+ /**
+ * Adds an endpoint descriptor as a child of this interface node.
+ * @param endpointNode The endpoint descriptor node to add to this interface node.
+ */
+ public void addEndpointNode(UsbDescriptorsEndpointNode endpointNode) {
+ mEndpointNodes.add(endpointNode);
+ }
+
+ /**
+ * Adds an Audio-class interface descriptor as a child of this interface node.
+ * @param acInterfaceNode The audio-class descriptor node to add to this interface node.
+ */
+ public void addACInterfaceNode(UsbDescriptorsACInterfaceNode acInterfaceNode) {
+ mACInterfaceNodes.add(acInterfaceNode);
+ }
+
+ @Override
+ public void report(ReportCanvas canvas) {
+ mInterfaceDescriptor.report(canvas);
+
+ // Audio Class Interfaces
+ if (mACInterfaceNodes.size() > 0) {
+ canvas.writeParagraph("Audio Class Interfaces", false);
+ canvas.openList();
+ for (UsbDescriptorsACInterfaceNode node : mACInterfaceNodes) {
+ node.report(canvas);
+ }
+ canvas.closeList();
+ }
+
+ // Endpoints
+ if (mEndpointNodes.size() > 0) {
+ canvas.writeParagraph("Endpoints", false);
+ canvas.openList();
+ for (UsbDescriptorsEndpointNode node : mEndpointNodes) {
+ node.report(canvas);
+ }
+ canvas.closeList();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.UsbACInterface;
+import com.android.server.usb.descriptors.UsbConfigDescriptor;
+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.UsbEndpointDescriptor;
+import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+import java.util.ArrayList;
+
+/*
+ * The general layout of the tree looks like this, though no guarentee about
+ * ordering of descriptors beyond the Device -> Config -> Interface.
+ *
+ * Device Descriptor
+ * +- Config Descriptor
+ * +- Interface Descriptor
+ * | +- Audio Class Interface
+ * | +- Audio Class Interface
+ * | +- Audio Class Interface
+ * | +- Endpoint Descriptor
+ * | +- Endpoint Descriptor
+ * +- Interface Descriptor
+ * +- Endpoint Descriptor
+ */
+/**
+ * @hide
+ *
+ * A class which builds a tree representation from the results of a (linear)
+ * parse of USB descriptors.
+ *
+ * @see {@link com.android.server.usb.descriptors.UsbDescriptorsParser UsbDescriptorsParser}
+ */
+public final class UsbDescriptorsTree {
+ private static final String TAG = "UsbDescriptorsTree";
+
+ private UsbDescriptorsDeviceNode mDeviceNode;
+ private UsbDescriptorsConfigNode mConfigNode; // being parsed
+ private UsbDescriptorsInterfaceNode mInterfaceNode; // being parsed
+
+ /**
+ * Adds THE device descriptor as the root of the tree.
+ */
+ private void addDeviceDescriptor(UsbDeviceDescriptor deviceDescriptor) {
+ mDeviceNode = new UsbDescriptorsDeviceNode(deviceDescriptor);
+ }
+
+ /**
+ * Adds A config descriptor to the tree.
+ */
+ private void addConfigDescriptor(UsbConfigDescriptor configDescriptor) {
+ mConfigNode = new UsbDescriptorsConfigNode(configDescriptor);
+ mDeviceNode.addConfigDescriptorNode(mConfigNode);
+ }
+
+ /**
+ * Adds AN interface descriptor to the current configuration in the tree.
+ */
+ private void addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDescriptor) {
+ mInterfaceNode = new UsbDescriptorsInterfaceNode(interfaceDescriptor);
+ mConfigNode.addInterfaceNode(mInterfaceNode);
+ }
+
+ /**
+ * Adds an endpoint descriptor to the current interface in the tree.
+ */
+ private void addEndpointDescriptor(UsbEndpointDescriptor endpointDescriptor) {
+ mInterfaceNode.addEndpointNode(new UsbDescriptorsEndpointNode(endpointDescriptor));
+ }
+
+ /**
+ * Adds an audio-class interface descriptor to the current interface in the tree.
+ */
+ private void addACInterface(UsbACInterface acInterface) {
+ mInterfaceNode.addACInterfaceNode(new UsbDescriptorsACInterfaceNode(acInterface));
+ }
+
+ /**
+ * Parses the linear descriptor list contained in the parser argument, into a tree
+ * representation corresponding to the logical structure of the USB descriptors.
+ */
+ public void parse(UsbDescriptorParser parser) {
+
+ ArrayList<UsbDescriptor> descriptors = parser.getDescriptors();
+
+ for (int descrIndex = 0; descrIndex < descriptors.size(); descrIndex++) {
+ UsbDescriptor descriptor = descriptors.get(descrIndex);
+ switch (descriptor.getType()) {
+ //
+ // Basic Descriptors
+ //
+ case UsbDescriptor.DESCRIPTORTYPE_DEVICE:
+ addDeviceDescriptor((UsbDeviceDescriptor) descriptor);
+ break;
+
+ case UsbDescriptor.DESCRIPTORTYPE_CONFIG:
+ addConfigDescriptor((UsbConfigDescriptor) descriptor);
+ break;
+
+ case UsbDescriptor.DESCRIPTORTYPE_INTERFACE:
+ addInterfaceDescriptor((UsbInterfaceDescriptor) descriptor);
+ break;
+
+ case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT:
+ addEndpointDescriptor((UsbEndpointDescriptor) descriptor);
+ break;
+
+ //
+ // Audio Class Descriptors
+ //
+ case UsbDescriptor.DESCRIPTORTYPE_AUDIO_INTERFACE:
+ addACInterface((UsbACInterface) descriptor);
+ break;
+
+ case UsbDescriptor.DESCRIPTORTYPE_AUDIO_ENDPOINT:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Generate a report of the descriptors tree.
+ */
+ public void report(ReportCanvas canvas) {
+ mDeviceNode.report(canvas);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+import com.android.server.usb.descriptors.report.Reporting;
+
+/**
+ * @hide
+ * A shared super class for UsbDescriptor tree nodes.
+ */
+public class UsbDescriptorsTreeNode implements Reporting {
+ private static final String TAG = "UsbDescriptorsTreeNode";
+
+ /**
+ * Implements generate a comprehehensive report of descriptor.
+ */
+ @Override
+ public void report(ReportCanvas canvas) {
+ }
+
+ /**
+ * Implements generate an abreviated report of descriptor.
+ */
+ @Override
+ public void shortReport(ReportCanvas canvas) {
+ }
+}