Merge "Adding USB audio-class 2.0 spec descriptors." into oc-mr1-dev
This commit is contained in:
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
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
|
||||
@@ -23,7 +27,7 @@ import android.annotation.NonNull;
|
||||
* 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 */
|
||||
@@ -103,6 +107,20 @@ public class ByteStream {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
@@ -111,11 +129,11 @@ public class ByteStream {
|
||||
* 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();
|
||||
}
|
||||
@@ -131,15 +149,31 @@ public class ByteStream {
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -15,18 +15,16 @@
|
||||
*/
|
||||
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
|
||||
@@ -34,16 +32,8 @@ public class UsbACHeader extends UsbACInterface {
|
||||
// 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() {
|
||||
@@ -60,9 +50,8 @@ public class UsbACHeader extends UsbACInterface {
|
||||
|
||||
@Override
|
||||
public int parseRawDescriptors(ByteStream stream) {
|
||||
mADCRelease = stream.unpackUsbWord();
|
||||
|
||||
mTotalLength = stream.unpackUsbWord();
|
||||
mTotalLength = stream.unpackUsbShort();
|
||||
if (mADCRelease >= 0x200) {
|
||||
mControls = stream.getByte();
|
||||
} else {
|
||||
@@ -75,4 +64,30 @@ public class UsbACHeader extends UsbACInterface {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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
|
||||
@@ -30,7 +32,7 @@ public class UsbACInputTerminal extends UsbACTerminal {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -55,10 +57,22 @@ public class UsbACInputTerminal extends UsbACTerminal {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -15,18 +15,20 @@
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -46,4 +48,13 @@ public class UsbACOutputTerminal extends UsbACTerminal {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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
|
||||
@@ -31,7 +33,7 @@ public class UsbASFormatI extends UsbASFormat {
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -51,10 +53,23 @@ public class UsbASFormatI extends UsbASFormat {
|
||||
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();
|
||||
@@ -74,4 +89,28 @@ public class UsbASFormatI extends UsbASFormat {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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.
|
||||
@@ -36,7 +38,7 @@ public class UsbASFormatII extends UsbASFormat {
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -58,8 +60,8 @@ public class UsbASFormatII extends UsbASFormat {
|
||||
|
||||
@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];
|
||||
@@ -69,4 +71,29 @@ public class UsbASFormatII extends UsbASFormat {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
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
|
||||
@@ -31,7 +34,7 @@ public class UsbASGeneral extends UsbACInterface {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -51,8 +54,20 @@ public class UsbASGeneral extends UsbACInterface {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ package com.android.server.usb.descriptors;
|
||||
* 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
|
||||
@@ -64,7 +64,7 @@ public class UsbACAudioControlEndpoint extends UsbACEndpoint {
|
||||
|
||||
mAddress = stream.getByte();
|
||||
mAttribs = stream.getByte();
|
||||
mMaxPacketSize = stream.unpackUsbWord();
|
||||
mMaxPacketSize = stream.unpackUsbShort();
|
||||
mInterval = stream.getByte();
|
||||
|
||||
return mLength;
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.android.server.usb.descriptors;
|
||||
* 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) {
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.util.Log;
|
||||
* 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.
|
||||
@@ -50,7 +50,7 @@ abstract class UsbACEndpoint extends UsbDescriptor {
|
||||
}
|
||||
|
||||
public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser,
|
||||
int length, byte type) {
|
||||
int length, byte type) {
|
||||
UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
|
||||
byte subClass = interfaceDesc.getUsbSubclass();
|
||||
switch (subClass) {
|
||||
|
||||
@@ -20,8 +20,8 @@ package com.android.server.usb.descriptors;
|
||||
* 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;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,16 @@ package com.android.server.usb.descriptors;
|
||||
|
||||
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;
|
||||
@@ -35,6 +38,11 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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;
|
||||
@@ -87,17 +95,39 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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);
|
||||
@@ -106,7 +136,14 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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:
|
||||
@@ -115,18 +152,24 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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:
|
||||
@@ -155,7 +198,6 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
// 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));
|
||||
@@ -173,10 +215,12 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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);
|
||||
@@ -187,4 +231,21 @@ public abstract class UsbACInterface extends UsbDescriptor {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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;
|
||||
@@ -49,4 +51,15 @@ public class UsbACMidiEndpoint extends UsbACEndpoint {
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -15,23 +15,14 @@
|
||||
*/
|
||||
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);
|
||||
@@ -53,20 +44,9 @@ public class UsbACMixerUnit extends UsbACInterface {
|
||||
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
|
||||
@@ -78,22 +58,6 @@ public class UsbACMixerUnit extends UsbACInterface {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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.
|
||||
@@ -62,4 +64,11 @@ public class UsbACSelectorUnit extends UsbACInterface {
|
||||
|
||||
return mLength;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void report(ReportCanvas canvas) {
|
||||
// super.report(canvas);
|
||||
//
|
||||
// //TODO
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -15,10 +15,15 @@
|
||||
*/
|
||||
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)
|
||||
@@ -46,9 +51,21 @@ public abstract class UsbACTerminal extends UsbACInterface {
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,19 +15,30 @@
|
||||
*/
|
||||
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);
|
||||
@@ -38,27 +49,59 @@ public abstract class UsbASFormat extends UsbACInterface {
|
||||
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.
|
||||
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);
|
||||
int acInterfaceSpec = parser.getACInterfaceSpec();
|
||||
|
||||
switch (formatType) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.android.server.usb.descriptors.report.UsbStrings;
|
||||
* 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;
|
||||
|
||||
@@ -33,7 +33,7 @@ public class UsbBinaryParser {
|
||||
|
||||
// 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++) {
|
||||
@@ -43,7 +43,7 @@ public class UsbBinaryParser {
|
||||
} 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++) {
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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
|
||||
@@ -35,6 +37,7 @@ public class UsbConfigDescriptor extends UsbDescriptor {
|
||||
|
||||
UsbConfigDescriptor(int length, byte type) {
|
||||
super(length, type);
|
||||
mHierarchyLevel = 2;
|
||||
}
|
||||
|
||||
public int getTotalLength() {
|
||||
@@ -63,7 +66,7 @@ public class UsbConfigDescriptor extends UsbDescriptor {
|
||||
|
||||
@Override
|
||||
public int parseRawDescriptors(ByteStream stream) {
|
||||
mTotalLength = stream.unpackUsbWord();
|
||||
mTotalLength = stream.unpackUsbShort();
|
||||
mNumInterfaces = stream.getByte();
|
||||
mConfigValue = stream.getByte();
|
||||
mConfigIndex = stream.getByte();
|
||||
@@ -72,4 +75,15 @@ public class UsbConfigDescriptor extends UsbDescriptor {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@ import android.hardware.usb.UsbConstants;
|
||||
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.
|
||||
*
|
||||
@@ -33,8 +37,10 @@ import android.util.Log;
|
||||
* @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.
|
||||
@@ -50,11 +56,15 @@ public abstract class UsbDescriptor {
|
||||
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
|
||||
@@ -147,6 +157,10 @@ public abstract class UsbDescriptor {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
public int getOverUnderRunCount() {
|
||||
return mOverUnderRunCount;
|
||||
}
|
||||
|
||||
public String getStatusString() {
|
||||
return sStatusStrings[mStatus];
|
||||
}
|
||||
@@ -165,14 +179,16 @@ public abstract class UsbDescriptor {
|
||||
// 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;
|
||||
@@ -220,4 +236,43 @@ public abstract class UsbDescriptor {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import java.util.ArrayList;
|
||||
* @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>();
|
||||
@@ -32,8 +32,34 @@ public class UsbDescriptorParser {
|
||||
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.
|
||||
@@ -44,7 +70,7 @@ public class UsbDescriptorParser {
|
||||
private UsbDescriptor allocDescriptor(ByteStream stream) {
|
||||
stream.resetReadCount();
|
||||
|
||||
int length = (int) stream.getByte() & 0x000000FF;
|
||||
int length = stream.getUnsignedByte();
|
||||
byte type = stream.getByte();
|
||||
|
||||
UsbDescriptor descriptor = null;
|
||||
@@ -99,7 +125,7 @@ public class UsbDescriptorParser {
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -135,14 +161,15 @@ public class UsbDescriptorParser {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,7 +224,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -220,7 +247,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -251,7 +278,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -274,8 +301,8 @@ public class UsbDescriptorParser {
|
||||
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
|
||||
@@ -284,7 +311,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -295,8 +322,8 @@ public class UsbDescriptorParser {
|
||||
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
|
||||
@@ -305,7 +332,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -328,6 +355,8 @@ public class UsbDescriptorParser {
|
||||
* to count on the peripheral being a headset.
|
||||
*/
|
||||
public boolean isInputHeadset() {
|
||||
// TEMP
|
||||
Log.i(TAG, "---- isInputHeadset() prob:" + (getInputHeadsetProbability() * 100f) + "%");
|
||||
return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER;
|
||||
}
|
||||
|
||||
@@ -348,8 +377,8 @@ public class UsbDescriptorParser {
|
||||
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
|
||||
@@ -358,7 +387,7 @@ public class UsbDescriptorParser {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
@@ -381,6 +410,8 @@ public class UsbDescriptorParser {
|
||||
* to count on the peripheral being a headset.
|
||||
*/
|
||||
public boolean isOutputHeadset() {
|
||||
// TEMP
|
||||
Log.i(TAG, "---- isOutputHeadset() prob:" + (getOutputHeadsetProbability() * 100f) + "%");
|
||||
return getOutputHeadsetProbability() >= OUT_HEADSET_TRIGGER;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,20 @@
|
||||
*/
|
||||
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
|
||||
@@ -39,6 +46,7 @@ package com.android.server.usb.descriptors;
|
||||
|
||||
UsbDeviceDescriptor(int length, byte type) {
|
||||
super(length, type);
|
||||
mHierarchyLevel = 1;
|
||||
}
|
||||
|
||||
public int getSpec() {
|
||||
@@ -91,14 +99,14 @@ package com.android.server.usb.descriptors;
|
||||
|
||||
@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();
|
||||
@@ -106,4 +114,35 @@ package com.android.server.usb.descriptors;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,36 +15,38 @@
|
||||
*/
|
||||
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 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_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 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.
|
||||
@@ -76,6 +78,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor {
|
||||
|
||||
public UsbEndpointDescriptor(int length, byte type) {
|
||||
super(length, type);
|
||||
mHierarchyLevel = 4;
|
||||
}
|
||||
|
||||
public byte getEndpointAddress() {
|
||||
@@ -106,7 +109,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor {
|
||||
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();
|
||||
@@ -114,4 +117,76 @@ public class UsbEndpointDescriptor extends UsbDescriptor {
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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.
|
||||
@@ -35,6 +37,7 @@ public class UsbHIDDescriptor extends UsbDescriptor {
|
||||
|
||||
public UsbHIDDescriptor(int length, byte type) {
|
||||
super(length, type);
|
||||
mHierarchyLevel = 3;
|
||||
}
|
||||
|
||||
public int getRelease() {
|
||||
@@ -59,12 +62,24 @@ public class UsbHIDDescriptor extends UsbDescriptor {
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
*/
|
||||
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;
|
||||
@@ -70,4 +72,11 @@ public class UsbInterfaceAssoc extends UsbDescriptor {
|
||||
|
||||
return mLength;
|
||||
}
|
||||
|
||||
// TODO - Report fields
|
||||
// @Override
|
||||
// public void report(ReportCanvas canvas) {
|
||||
// super.report(canvas);
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
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
|
||||
@@ -33,6 +36,7 @@ public class UsbInterfaceDescriptor extends UsbDescriptor {
|
||||
|
||||
UsbInterfaceDescriptor(int length, byte type) {
|
||||
super(length, type);
|
||||
mHierarchyLevel = 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,4 +79,27 @@ public class UsbInterfaceDescriptor extends UsbDescriptor {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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);
|
||||
@@ -33,4 +35,13 @@ public class UsbMSMidiHeader extends UsbACInterface {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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);
|
||||
@@ -33,4 +35,13 @@ public class UsbMSMidiInputJack extends UsbACInterface {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
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);
|
||||
@@ -33,4 +35,13 @@ public class UsbMSMidiOutputJack extends UsbACInterface {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ package com.android.server.usb.descriptors;
|
||||
* 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;
|
||||
|
||||
@@ -19,8 +19,8 @@ package com.android.server.usb.descriptors;
|
||||
* @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);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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>");
|
||||
}
|
||||
}
|
||||
@@ -1,572 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
@@ -16,12 +16,16 @@
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
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;
|
||||
|
||||
@@ -25,7 +26,7 @@ import java.util.HashMap;
|
||||
* @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;
|
||||
@@ -35,6 +36,7 @@ public class UsbStrings {
|
||||
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>();
|
||||
@@ -70,6 +72,11 @@ public class UsbStrings {
|
||||
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() {
|
||||
@@ -213,6 +220,29 @@ public class UsbStrings {
|
||||
? 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.
|
||||
*/
|
||||
@@ -224,10 +254,11 @@ public class UsbStrings {
|
||||
initAudioSubclassNames();
|
||||
initAudioEncodingNames();
|
||||
initTerminalNames();
|
||||
initFormatNames();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes string tables.
|
||||
* Deinitializes string tables.
|
||||
*/
|
||||
public static void releaseUsbStrings() {
|
||||
sDescriptorNames = null;
|
||||
@@ -309,4 +340,11 @@ public class UsbStrings {
|
||||
: "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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user