Loading services/usb/java/com/android/server/usb/descriptors/ByteStream.java +43 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 */ Loading Loading @@ -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 Loading @@ -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(); } Loading @@ -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. Loading services/usb/java/com/android/server/usb/descriptors/UsbACHeader.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACHeader.java +33 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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() { Loading @@ -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 { Loading @@ -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(); } } services/usb/java/com/android/server/usb/descriptors/UsbACInputTerminal.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACInputTerminal.java +18 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } Loading @@ -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(); } } services/usb/java/com/android/server/usb/descriptors/Usb10ACMixerUnit.java 0 → 100644 +108 −0 Original line number Diff line number Diff line /* * 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(); } } services/usb/java/com/android/server/usb/descriptors/UsbACOutputTerminal.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACOutputTerminal.java +14 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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(); } } Loading
services/usb/java/com/android/server/usb/descriptors/ByteStream.java +43 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 */ Loading Loading @@ -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 Loading @@ -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(); } Loading @@ -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. Loading
services/usb/java/com/android/server/usb/descriptors/UsbACHeader.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACHeader.java +33 −18 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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() { Loading @@ -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 { Loading @@ -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(); } }
services/usb/java/com/android/server/usb/descriptors/UsbACInputTerminal.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACInputTerminal.java +18 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } Loading @@ -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(); } }
services/usb/java/com/android/server/usb/descriptors/Usb10ACMixerUnit.java 0 → 100644 +108 −0 Original line number Diff line number Diff line /* * 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(); } }
services/usb/java/com/android/server/usb/descriptors/UsbACOutputTerminal.java→services/usb/java/com/android/server/usb/descriptors/Usb10ACOutputTerminal.java +14 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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(); } }