// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.media;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
/**
* Owned by its native counterpart declared in usb_midi_device_android.h.
* Refer to that class for general comments.
*/
@JNINamespace("media")
class UsbMidiDeviceAndroid {
/**
* A connection handle for this device.
*/
private UsbDeviceConnection mConnection;
/**
* A map from endpoint number to UsbEndpoint.
*/
private final Map<Integer, UsbEndpoint> mEndpointMap;
/**
* A map from UsbEndpoint to UsbRequest associated to it.
*/
private final Map<UsbEndpoint, UsbRequest> mRequestMap;
/**
* Audio interface subclass code for MIDI.
*/
static final int MIDI_SUBCLASS = 3;
/**
* Constructs a UsbMidiDeviceAndroid.
* @param manager
* @param device The USB device which this object is assocated with.
*/
UsbMidiDeviceAndroid(UsbManager manager, UsbDevice device) {
mConnection = manager.openDevice(device);
mEndpointMap = new HashMap<Integer, UsbEndpoint>();
mRequestMap = new HashMap<UsbEndpoint, UsbRequest>();
for (int i = 0; i < device.getInterfaceCount(); ++i) {
UsbInterface iface = device.getInterface(i);
if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_AUDIO ||
iface.getInterfaceSubclass() != MIDI_SUBCLASS) {
continue;
}
mConnection.claimInterface(iface, true);
for (int j = 0; j < iface.getEndpointCount(); ++j) {
UsbEndpoint endpoint = iface.getEndpoint(j);
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
mEndpointMap.put(endpoint.getEndpointNumber(), endpoint);
}
}
}
}
/**
* Sends a USB-MIDI data to the device.
* @param endpointNumber The endpoint number of the destination endpoint.
* @param bs The data to be sent.
*/
@CalledByNative
void send(int endpointNumber, byte[] bs) {
if (mConnection == null) {
return;
}
if (!mEndpointMap.containsKey(endpointNumber)) {
return;
}
UsbEndpoint endpoint = mEndpointMap.get(endpointNumber);
UsbRequest request;
if (mRequestMap.containsKey(endpoint)) {
request = mRequestMap.get(endpoint);
} else {
request = new UsbRequest();
request.initialize(mConnection, endpoint);
mRequestMap.put(endpoint, request);
}
request.queue(ByteBuffer.wrap(bs), bs.length);
}
/**
* Returns the descriptors bytes of this device.
* @return The descriptors bytes of this device.
*/
@CalledByNative
byte[] getDescriptors() {
if (mConnection == null) {
return new byte[0];
}
return mConnection.getRawDescriptors();
}
/**
* Closes the device connection.
*/
@CalledByNative
void close() {
mEndpointMap.clear();
for (UsbRequest request : mRequestMap.values()) {
request.close();
}
mRequestMap.clear();
if (mConnection != null) {
mConnection.close();
mConnection = null;
}
}
}