UsbMidiDeviceAndroid.java revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.media;
6
7import android.hardware.usb.UsbConstants;
8import android.hardware.usb.UsbDevice;
9import android.hardware.usb.UsbDeviceConnection;
10import android.hardware.usb.UsbEndpoint;
11import android.hardware.usb.UsbInterface;
12import android.hardware.usb.UsbManager;
13import android.hardware.usb.UsbRequest;
14
15import org.chromium.base.CalledByNative;
16import org.chromium.base.JNINamespace;
17
18import java.nio.ByteBuffer;
19import java.util.HashMap;
20import java.util.Map;
21
22/**
23 * Owned by its native counterpart declared in usb_midi_device_android.h.
24 * Refer to that class for general comments.
25 */
26@JNINamespace("media")
27class UsbMidiDeviceAndroid {
28    /**
29     * A connection handle for this device.
30     */
31    private UsbDeviceConnection mConnection;
32
33    /**
34     * A map from endpoint number to UsbEndpoint.
35     */
36    private final Map<Integer, UsbEndpoint> mEndpointMap;
37
38    /**
39     * A map from UsbEndpoint to UsbRequest associated to it.
40     */
41    private final Map<UsbEndpoint, UsbRequest> mRequestMap;
42
43    /**
44     * Audio interface subclass code for MIDI.
45     */
46    static final int MIDI_SUBCLASS = 3;
47
48    /**
49     * Constructs a UsbMidiDeviceAndroid.
50     * @param manager
51     * @param device The USB device which this object is assocated with.
52     */
53    UsbMidiDeviceAndroid(UsbManager manager, UsbDevice device) {
54        mConnection = manager.openDevice(device);
55        mEndpointMap = new HashMap<Integer, UsbEndpoint>();
56        mRequestMap = new HashMap<UsbEndpoint, UsbRequest>();
57
58        for (int i = 0; i < device.getInterfaceCount(); ++i) {
59            UsbInterface iface = device.getInterface(i);
60            if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_AUDIO ||
61                iface.getInterfaceSubclass() != MIDI_SUBCLASS) {
62                continue;
63            }
64            mConnection.claimInterface(iface, true);
65            for (int j = 0; j < iface.getEndpointCount(); ++j) {
66                UsbEndpoint endpoint = iface.getEndpoint(j);
67                if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
68                    mEndpointMap.put(endpoint.getEndpointNumber(), endpoint);
69                }
70            }
71        }
72    }
73
74    /**
75     * Sends a USB-MIDI data to the device.
76     * @param endpointNumber The endpoint number of the destination endpoint.
77     * @param bs The data to be sent.
78     */
79    @CalledByNative
80    void send(int endpointNumber, byte[] bs) {
81        if (mConnection == null) {
82            return;
83        }
84        if (!mEndpointMap.containsKey(endpointNumber)) {
85            return;
86        }
87        UsbEndpoint endpoint = mEndpointMap.get(endpointNumber);
88        UsbRequest request;
89        if (mRequestMap.containsKey(endpoint)) {
90            request = mRequestMap.get(endpoint);
91        } else {
92            request = new UsbRequest();
93            request.initialize(mConnection, endpoint);
94            mRequestMap.put(endpoint, request);
95        }
96        request.queue(ByteBuffer.wrap(bs), bs.length);
97    }
98
99    /**
100     * Returns the descriptors bytes of this device.
101     * @return The descriptors bytes of this device.
102     */
103    @CalledByNative
104    byte[] getDescriptors() {
105        if (mConnection == null) {
106            return new byte[0];
107        }
108        return mConnection.getRawDescriptors();
109    }
110
111    /**
112     * Closes the device connection.
113     */
114    @CalledByNative
115    void close() {
116        mEndpointMap.clear();
117        for (UsbRequest request : mRequestMap.values()) {
118            request.close();
119        }
120        mRequestMap.clear();
121        if (mConnection != null) {
122            mConnection.close();
123            mConnection = null;
124        }
125    }
126}
127