Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a57bc7f authored by Mike Lockwood's avatar Mike Lockwood
Browse files

MidiManager: Add USB peripheral MIDI support

This allows the android device to appear as a USB MIDI device to
a USB host (like a Mac or a PC) using the f_midi USB gadget driver.

Change-Id: I14f1ba73bcce2c894e77efb8810beac4ffe246d8
parent 293b7b4f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ public class UsbManager {
     * accessory function is enabled
     * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
     * audio source function is enabled
     * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
     * MIDI function is enabled
     * </ul>
     *
     * {@hide}
@@ -187,6 +189,14 @@ public class UsbManager {
     */
    public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";

    /**
     * Name of the MIDI USB function.
     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
     *
     * {@hide}
     */
    public static final String USB_FUNCTION_MIDI = "midi";

    /**
     * Name of the Accessory USB function.
     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+5 −0
Original line number Diff line number Diff line
@@ -5188,4 +5188,9 @@
    <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
    <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>

    <!-- Manufacturer name for USB MIDI Peripheral port -->
    <string name="usb_midi_peripheral_manufacturer_name">Android</string>
    <!-- Model name for USB MIDI Peripheral port -->
    <string name="usb_midi_peripheral_model_name">USB Peripheral Port</string>

</resources>
+3 −0
Original line number Diff line number Diff line
@@ -2156,4 +2156,7 @@
  <java-symbol type="bool" name="config_use_sim_language_file" />
  <java-symbol type="bool" name="config_LTE_eri_for_network_name" />
  <java-symbol type="bool" name="config_defaultInTouchMode" />

  <java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
  <java-symbol type="string" name="usb_midi_peripheral_model_name" />
</resources>
+34 −1
Original line number Diff line number Diff line
@@ -20,12 +20,15 @@ import android.alsa.AlsaCardsParser;
import android.alsa.AlsaDevicesParser;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.midi.MidiDeviceInfo;
import android.os.FileObserver;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -73,6 +76,9 @@ public final class UsbAlsaManager {

    private UsbAudioDevice mSelectedAudioDevice = null;

    // UsbMidiDevice for USB peripheral mode (gadget) device
    private UsbMidiDevice mPeripheralMidiDevice = null;

    private final class AlsaDevice {
        public static final int TYPE_UNKNOWN = 0;
        public static final int TYPE_PLAYBACK = 1;
@@ -391,7 +397,17 @@ public final class UsbAlsaManager {
                int device = mDevicesParser.getDefaultDeviceNum(addedCard);
                AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
                if (alsaDevice != null) {
                    UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, usbDevice,
                    Bundle properties = new Bundle();
                    properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER,
                            usbDevice.getManufacturerName());
                    properties.putString(MidiDeviceInfo.PROPERTY_MODEL, usbDevice.getProductName());
                    properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
                            usbDevice.getSerialNumber());
                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard);
                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, alsaDevice.mDevice);
                    properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);

                    UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
                            alsaDevice.mCard, alsaDevice.mDevice);
                    if (usbMidiDevice != null) {
                        mMidiDevices.put(usbDevice, usbMidiDevice);
@@ -437,6 +453,23 @@ public final class UsbAlsaManager {
        }
    }

   /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
        if (enabled) {
            Bundle properties = new Bundle();
            Resources r = mContext.getResources();
            properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
                    com.android.internal.R.string.usb_midi_peripheral_manufacturer_name));
            properties.putString(MidiDeviceInfo.PROPERTY_MODEL, r.getString(
                    com.android.internal.R.string.usb_midi_peripheral_model_name));
            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
            mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
        } else if (mPeripheralMidiDevice != null) {
            IoUtils.closeQuietly(mPeripheralMidiDevice);
            mPeripheralMidiDevice = null;
        }
   }

    //
    // Devices List
    //
+31 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.database.ContentObserver;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.midi.MidiDeviceInfo;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -85,6 +86,8 @@ public class UsbDeviceManager {
            "/sys/class/android_usb/android0/f_rndis/ethaddr";
    private static final String AUDIO_SOURCE_PCM_PATH =
            "/sys/class/android_usb/android0/f_audio_source/pcm";
    private static final String MIDI_ALSA_PATH =
            "/sys/class/android_usb/android0/f_midi/alsa";

    private static final int MSG_UPDATE_STATE = 0;
    private static final int MSG_ENABLE_ADB = 1;
@@ -124,6 +127,7 @@ public class UsbDeviceManager {
    private boolean mUseUsbNotification;
    private boolean mAdbEnabled;
    private boolean mAudioSourceEnabled;
    private boolean mMidiEnabled;
    private Map<String, List<Pair<String, String>>> mOemModeMap;
    private String[] mAccessoryStrings;
    private UsbDebuggingManager mDebuggingManager;
@@ -618,6 +622,31 @@ public class UsbDeviceManager {
            }
        }

        private void updateMidiFunction() {
            boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
            if (enabled != mMidiEnabled) {
                int card = -1;
                int device = -1;

                if (enabled) {
                    Scanner scanner = null;
                    try {
                        scanner = new Scanner(new File(MIDI_ALSA_PATH));
                        card = scanner.nextInt();
                        device = scanner.nextInt();
                    } catch (FileNotFoundException e) {
                        Slog.e(TAG, "could not open MIDI PCM file", e);
                    } finally {
                        if (scanner != null) {
                            scanner.close();
                        }
                    }
                }
                mUsbAlsaManager.setPeripheralMidiState(enabled, card, device);
                mMidiEnabled = enabled;
            }
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
@@ -636,6 +665,7 @@ public class UsbDeviceManager {
                    if (mBootCompleted) {
                        updateUsbState();
                        updateAudioSourceFunction();
                        updateMidiFunction();
                    }
                    break;
                case MSG_ENABLE_ADB:
@@ -651,6 +681,7 @@ public class UsbDeviceManager {
                    updateAdbNotification();
                    updateUsbState();
                    updateAudioSourceFunction();
                    updateMidiFunction();
                    break;
                case MSG_BOOT_COMPLETED:
                    mBootCompleted = true;
Loading