Loading services/usb/java/com/android/server/usb/UsbAlsaManager.java +70 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import libcore.io.IoUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; /** Loading Loading @@ -106,6 +107,12 @@ public final class UsbAlsaManager { return false; } /** * List of connected MIDI devices */ private final HashMap<String, UsbMidiDevice> mMidiDevices = new HashMap<String, UsbMidiDevice>(); // UsbMidiDevice for USB peripheral mode (gadget) device private UsbMidiDevice mPeripheralMidiDevice = null; Loading Loading @@ -249,6 +256,8 @@ public final class UsbAlsaManager { } } addMidiDevice(deviceAddress, usbDevice, parser, cardRec); logDevices("deviceAdded()"); if (DEBUG) { Loading @@ -256,6 +265,54 @@ public final class UsbAlsaManager { } } private void addMidiDevice(String deviceAddress, UsbDevice usbDevice, UsbDescriptorParser parser, AlsaCardsParser.AlsaCardRecord cardRec) { boolean hasMidi = parser.hasMIDIInterface(); // UsbHostManager will create UsbDirectMidiDevices instead if MIDI 2 is supported. boolean hasMidi2 = parser.containsUniversalMidiDeviceEndpoint(); if (DEBUG) { Slog.d(TAG, "hasMidi: " + hasMidi + " mHasMidiFeature:" + mHasMidiFeature); Slog.d(TAG, "hasMidi2: " + hasMidi2); } if (mHasMidiFeature && hasMidi && !hasMidi2) { Bundle properties = new Bundle(); String manufacturer = usbDevice.getManufacturerName(); String product = usbDevice.getProductName(); String version = usbDevice.getVersion(); String name; if (manufacturer == null || manufacturer.isEmpty()) { name = product; } else if (product == null || product.isEmpty()) { name = manufacturer; } else { name = manufacturer + " " + product; } properties.putString(MidiDeviceInfo.PROPERTY_NAME, name); properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer); properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product); properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version); properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, cardRec.getCardNum()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, 0 /*deviceNum*/); properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice); int numLegacyMidiInputs = parser.calculateNumLegacyMidiInputs(); int numLegacyMidiOutputs = parser.calculateNumLegacyMidiOutputs(); if (DEBUG) { Slog.d(TAG, "numLegacyMidiInputs: " + numLegacyMidiInputs); Slog.d(TAG, "numLegacyMidiOutputs:" + numLegacyMidiOutputs); } UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties, cardRec.getCardNum(), 0 /*device*/, numLegacyMidiInputs, numLegacyMidiOutputs); if (usbMidiDevice != null) { mMidiDevices.put(deviceAddress, usbMidiDevice); } } } /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) { if (DEBUG) { Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")"); Loading @@ -269,6 +326,13 @@ public final class UsbAlsaManager { selectDefaultDevice(); // if there any external devices left, select one of them } // MIDI UsbMidiDevice usbMidiDevice = mMidiDevices.remove(deviceAddress); if (usbMidiDevice != null) { Slog.i(TAG, "USB MIDI Device Removed: " + deviceAddress); IoUtils.closeQuietly(usbMidiDevice); } logDevices("usbDeviceRemoved()"); } Loading Loading @@ -324,6 +388,12 @@ public final class UsbAlsaManager { usbAlsaDevice.dump(dump, "alsa_devices", UsbAlsaManagerProto.ALSA_DEVICES); } for (String deviceAddr : mMidiDevices.keySet()) { // A UsbMidiDevice does not have a handle to the UsbDevice anymore mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "midi_devices", UsbAlsaManagerProto.MIDI_DEVICES); } dump.end(token); } Loading services/usb/java/com/android/server/usb/UsbHostManager.java +13 −8 Original line number Diff line number Diff line Loading @@ -444,9 +444,13 @@ public class UsbHostManager { } else { Slog.e(TAG, "Universal Midi Device is null."); } } // Use UsbDirectMidiDevice only if this supports MIDI 2.0 as well. // ALSA removes the audio sound card if MIDI interfaces are removed. // This means that as long as ALSA is used for audio, MIDI 1.0 USB // devices should use the ALSA path for MIDI. if (parser.containsLegacyMidiDeviceEndpoint()) { UsbDirectMidiDevice midiDevice = UsbDirectMidiDevice.create(mContext, midiDevice = UsbDirectMidiDevice.create(mContext, newDevice, parser, false, uniqueUsbDeviceIdentifier); if (midiDevice != null) { midiDevices.add(midiDevice); Loading @@ -454,6 +458,7 @@ public class UsbHostManager { Slog.e(TAG, "Legacy Midi Device is null."); } } } if (!midiDevices.isEmpty()) { mMidiDevices.put(deviceAddress, midiDevices); Loading services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ public final class UsbConfigDescriptor extends UsbDescriptor { mInterfaceDescriptors.add(interfaceDesc); } ArrayList<UsbInterfaceDescriptor> getInterfaceDescriptors() { return mInterfaceDescriptors; } private boolean isAudioInterface(UsbInterfaceDescriptor descriptor) { return descriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO && descriptor.getUsbSubclass() == UsbDescriptor.AUDIO_AUDIOSTREAMING; Loading services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +83 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public final class UsbDescriptorParser { private UsbDeviceDescriptor mDeviceDescriptor; private UsbConfigDescriptor mCurConfigDescriptor; private UsbInterfaceDescriptor mCurInterfaceDescriptor; private UsbEndpointDescriptor mCurEndpointDescriptor; // The AudioClass spec implemented by the AudioClass Interfaces // This may well be different than the overall USB Spec. Loading Loading @@ -165,7 +166,7 @@ public final class UsbDescriptorParser { break; case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT: descriptor = new UsbEndpointDescriptor(length, type); descriptor = mCurEndpointDescriptor = new UsbEndpointDescriptor(length, type); if (mCurInterfaceDescriptor != null) { mCurInterfaceDescriptor.addEndpointDescriptor( (UsbEndpointDescriptor) descriptor); Loading Loading @@ -265,6 +266,9 @@ public final class UsbDescriptorParser { + Integer.toHexString(subClass)); break; } if (mCurEndpointDescriptor != null && descriptor != null) { mCurEndpointDescriptor.setClassSpecificEndpointDescriptor(descriptor); } } break; Loading Loading @@ -795,6 +799,84 @@ public final class UsbDescriptorParser { return count; } /** * @hide */ private int calculateNumLegacyMidiPorts(boolean isOutput) { // Only look at the first config. UsbConfigDescriptor configDescriptor = null; for (UsbDescriptor descriptor : mDescriptors) { if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_CONFIG) { if (descriptor instanceof UsbConfigDescriptor) { configDescriptor = (UsbConfigDescriptor) descriptor; break; } else { Log.w(TAG, "Unrecognized Config l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } } if (configDescriptor == null) { Log.w(TAG, "Config not found"); return 0; } ArrayList<UsbInterfaceDescriptor> legacyMidiInterfaceDescriptors = new ArrayList<UsbInterfaceDescriptor>(); for (UsbInterfaceDescriptor interfaceDescriptor : configDescriptor.getInterfaceDescriptors()) { if (interfaceDescriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO) { if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) { UsbDescriptor midiHeaderDescriptor = interfaceDescriptor.getMidiHeaderInterfaceDescriptor(); if (midiHeaderDescriptor != null) { if (midiHeaderDescriptor instanceof UsbMSMidiHeader) { UsbMSMidiHeader midiHeader = (UsbMSMidiHeader) midiHeaderDescriptor; if (midiHeader.getMidiStreamingClass() == MS_MIDI_1_0) { legacyMidiInterfaceDescriptors.add(interfaceDescriptor); } } } } } } int count = 0; for (UsbInterfaceDescriptor interfaceDescriptor : legacyMidiInterfaceDescriptors) { for (int i = 0; i < interfaceDescriptor.getNumEndpoints(); i++) { UsbEndpointDescriptor endpoint = interfaceDescriptor.getEndpointDescriptor(i); // 0 is output, 1 << 7 is input. if ((endpoint.getDirection() == 0) == isOutput) { UsbDescriptor classSpecificEndpointDescriptor = endpoint.getClassSpecificEndpointDescriptor(); if (classSpecificEndpointDescriptor != null && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) { UsbACMidi10Endpoint midiEndpoint = (UsbACMidi10Endpoint) classSpecificEndpointDescriptor; count += midiEndpoint.getNumJacks(); } } } } return count; } /** * @hide */ public int calculateNumLegacyMidiInputs() { return calculateNumLegacyMidiPorts(false /*isOutput*/); } /** * @hide */ public int calculateNumLegacyMidiOutputs() { return calculateNumLegacyMidiPorts(true /*isOutput*/); } /** * @hide */ Loading services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java +10 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ public class UsbEndpointDescriptor extends UsbDescriptor { private byte mRefresh; private byte mSyncAddress; private UsbDescriptor mClassSpecificEndpointDescriptor; public UsbEndpointDescriptor(int length, byte type) { super(length, type); mHierarchyLevel = 4; Loading Loading @@ -112,6 +114,14 @@ public class UsbEndpointDescriptor extends UsbDescriptor { return mEndpointAddress & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION; } void setClassSpecificEndpointDescriptor(UsbDescriptor descriptor) { mClassSpecificEndpointDescriptor = descriptor; } UsbDescriptor getClassSpecificEndpointDescriptor() { return mClassSpecificEndpointDescriptor; } /** * Returns a UsbEndpoint that this UsbEndpointDescriptor is describing. */ Loading Loading
services/usb/java/com/android/server/usb/UsbAlsaManager.java +70 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import libcore.io.IoUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; /** Loading Loading @@ -106,6 +107,12 @@ public final class UsbAlsaManager { return false; } /** * List of connected MIDI devices */ private final HashMap<String, UsbMidiDevice> mMidiDevices = new HashMap<String, UsbMidiDevice>(); // UsbMidiDevice for USB peripheral mode (gadget) device private UsbMidiDevice mPeripheralMidiDevice = null; Loading Loading @@ -249,6 +256,8 @@ public final class UsbAlsaManager { } } addMidiDevice(deviceAddress, usbDevice, parser, cardRec); logDevices("deviceAdded()"); if (DEBUG) { Loading @@ -256,6 +265,54 @@ public final class UsbAlsaManager { } } private void addMidiDevice(String deviceAddress, UsbDevice usbDevice, UsbDescriptorParser parser, AlsaCardsParser.AlsaCardRecord cardRec) { boolean hasMidi = parser.hasMIDIInterface(); // UsbHostManager will create UsbDirectMidiDevices instead if MIDI 2 is supported. boolean hasMidi2 = parser.containsUniversalMidiDeviceEndpoint(); if (DEBUG) { Slog.d(TAG, "hasMidi: " + hasMidi + " mHasMidiFeature:" + mHasMidiFeature); Slog.d(TAG, "hasMidi2: " + hasMidi2); } if (mHasMidiFeature && hasMidi && !hasMidi2) { Bundle properties = new Bundle(); String manufacturer = usbDevice.getManufacturerName(); String product = usbDevice.getProductName(); String version = usbDevice.getVersion(); String name; if (manufacturer == null || manufacturer.isEmpty()) { name = product; } else if (product == null || product.isEmpty()) { name = manufacturer; } else { name = manufacturer + " " + product; } properties.putString(MidiDeviceInfo.PROPERTY_NAME, name); properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer); properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product); properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version); properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, cardRec.getCardNum()); properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, 0 /*deviceNum*/); properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice); int numLegacyMidiInputs = parser.calculateNumLegacyMidiInputs(); int numLegacyMidiOutputs = parser.calculateNumLegacyMidiOutputs(); if (DEBUG) { Slog.d(TAG, "numLegacyMidiInputs: " + numLegacyMidiInputs); Slog.d(TAG, "numLegacyMidiOutputs:" + numLegacyMidiOutputs); } UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties, cardRec.getCardNum(), 0 /*device*/, numLegacyMidiInputs, numLegacyMidiOutputs); if (usbMidiDevice != null) { mMidiDevices.put(deviceAddress, usbMidiDevice); } } } /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) { if (DEBUG) { Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")"); Loading @@ -269,6 +326,13 @@ public final class UsbAlsaManager { selectDefaultDevice(); // if there any external devices left, select one of them } // MIDI UsbMidiDevice usbMidiDevice = mMidiDevices.remove(deviceAddress); if (usbMidiDevice != null) { Slog.i(TAG, "USB MIDI Device Removed: " + deviceAddress); IoUtils.closeQuietly(usbMidiDevice); } logDevices("usbDeviceRemoved()"); } Loading Loading @@ -324,6 +388,12 @@ public final class UsbAlsaManager { usbAlsaDevice.dump(dump, "alsa_devices", UsbAlsaManagerProto.ALSA_DEVICES); } for (String deviceAddr : mMidiDevices.keySet()) { // A UsbMidiDevice does not have a handle to the UsbDevice anymore mMidiDevices.get(deviceAddr).dump(deviceAddr, dump, "midi_devices", UsbAlsaManagerProto.MIDI_DEVICES); } dump.end(token); } Loading
services/usb/java/com/android/server/usb/UsbHostManager.java +13 −8 Original line number Diff line number Diff line Loading @@ -444,9 +444,13 @@ public class UsbHostManager { } else { Slog.e(TAG, "Universal Midi Device is null."); } } // Use UsbDirectMidiDevice only if this supports MIDI 2.0 as well. // ALSA removes the audio sound card if MIDI interfaces are removed. // This means that as long as ALSA is used for audio, MIDI 1.0 USB // devices should use the ALSA path for MIDI. if (parser.containsLegacyMidiDeviceEndpoint()) { UsbDirectMidiDevice midiDevice = UsbDirectMidiDevice.create(mContext, midiDevice = UsbDirectMidiDevice.create(mContext, newDevice, parser, false, uniqueUsbDeviceIdentifier); if (midiDevice != null) { midiDevices.add(midiDevice); Loading @@ -454,6 +458,7 @@ public class UsbHostManager { Slog.e(TAG, "Legacy Midi Device is null."); } } } if (!midiDevices.isEmpty()) { mMidiDevices.put(deviceAddress, midiDevices); Loading
services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java +4 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,10 @@ public final class UsbConfigDescriptor extends UsbDescriptor { mInterfaceDescriptors.add(interfaceDesc); } ArrayList<UsbInterfaceDescriptor> getInterfaceDescriptors() { return mInterfaceDescriptors; } private boolean isAudioInterface(UsbInterfaceDescriptor descriptor) { return descriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO && descriptor.getUsbSubclass() == UsbDescriptor.AUDIO_AUDIOSTREAMING; Loading
services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +83 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public final class UsbDescriptorParser { private UsbDeviceDescriptor mDeviceDescriptor; private UsbConfigDescriptor mCurConfigDescriptor; private UsbInterfaceDescriptor mCurInterfaceDescriptor; private UsbEndpointDescriptor mCurEndpointDescriptor; // The AudioClass spec implemented by the AudioClass Interfaces // This may well be different than the overall USB Spec. Loading Loading @@ -165,7 +166,7 @@ public final class UsbDescriptorParser { break; case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT: descriptor = new UsbEndpointDescriptor(length, type); descriptor = mCurEndpointDescriptor = new UsbEndpointDescriptor(length, type); if (mCurInterfaceDescriptor != null) { mCurInterfaceDescriptor.addEndpointDescriptor( (UsbEndpointDescriptor) descriptor); Loading Loading @@ -265,6 +266,9 @@ public final class UsbDescriptorParser { + Integer.toHexString(subClass)); break; } if (mCurEndpointDescriptor != null && descriptor != null) { mCurEndpointDescriptor.setClassSpecificEndpointDescriptor(descriptor); } } break; Loading Loading @@ -795,6 +799,84 @@ public final class UsbDescriptorParser { return count; } /** * @hide */ private int calculateNumLegacyMidiPorts(boolean isOutput) { // Only look at the first config. UsbConfigDescriptor configDescriptor = null; for (UsbDescriptor descriptor : mDescriptors) { if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_CONFIG) { if (descriptor instanceof UsbConfigDescriptor) { configDescriptor = (UsbConfigDescriptor) descriptor; break; } else { Log.w(TAG, "Unrecognized Config l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } } if (configDescriptor == null) { Log.w(TAG, "Config not found"); return 0; } ArrayList<UsbInterfaceDescriptor> legacyMidiInterfaceDescriptors = new ArrayList<UsbInterfaceDescriptor>(); for (UsbInterfaceDescriptor interfaceDescriptor : configDescriptor.getInterfaceDescriptors()) { if (interfaceDescriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO) { if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) { UsbDescriptor midiHeaderDescriptor = interfaceDescriptor.getMidiHeaderInterfaceDescriptor(); if (midiHeaderDescriptor != null) { if (midiHeaderDescriptor instanceof UsbMSMidiHeader) { UsbMSMidiHeader midiHeader = (UsbMSMidiHeader) midiHeaderDescriptor; if (midiHeader.getMidiStreamingClass() == MS_MIDI_1_0) { legacyMidiInterfaceDescriptors.add(interfaceDescriptor); } } } } } } int count = 0; for (UsbInterfaceDescriptor interfaceDescriptor : legacyMidiInterfaceDescriptors) { for (int i = 0; i < interfaceDescriptor.getNumEndpoints(); i++) { UsbEndpointDescriptor endpoint = interfaceDescriptor.getEndpointDescriptor(i); // 0 is output, 1 << 7 is input. if ((endpoint.getDirection() == 0) == isOutput) { UsbDescriptor classSpecificEndpointDescriptor = endpoint.getClassSpecificEndpointDescriptor(); if (classSpecificEndpointDescriptor != null && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) { UsbACMidi10Endpoint midiEndpoint = (UsbACMidi10Endpoint) classSpecificEndpointDescriptor; count += midiEndpoint.getNumJacks(); } } } } return count; } /** * @hide */ public int calculateNumLegacyMidiInputs() { return calculateNumLegacyMidiPorts(false /*isOutput*/); } /** * @hide */ public int calculateNumLegacyMidiOutputs() { return calculateNumLegacyMidiPorts(true /*isOutput*/); } /** * @hide */ Loading
services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java +10 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,8 @@ public class UsbEndpointDescriptor extends UsbDescriptor { private byte mRefresh; private byte mSyncAddress; private UsbDescriptor mClassSpecificEndpointDescriptor; public UsbEndpointDescriptor(int length, byte type) { super(length, type); mHierarchyLevel = 4; Loading Loading @@ -112,6 +114,14 @@ public class UsbEndpointDescriptor extends UsbDescriptor { return mEndpointAddress & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION; } void setClassSpecificEndpointDescriptor(UsbDescriptor descriptor) { mClassSpecificEndpointDescriptor = descriptor; } UsbDescriptor getClassSpecificEndpointDescriptor() { return mClassSpecificEndpointDescriptor; } /** * Returns a UsbEndpoint that this UsbEndpointDescriptor is describing. */ Loading