com_android_server_UsbMidiDevice.cpp revision b7ce094c9e546c4a802bd8ce3a43592979a5e3df
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "UsbMidiDeviceJNI"
18#define LOG_NDEBUG 0
19#include "utils/Log.h"
20
21#include "jni.h"
22#include "JNIHelp.h"
23#include "android_runtime/AndroidRuntime.h"
24#include "android_runtime/Log.h"
25
26#include <stdio.h>
27#include <errno.h>
28#include <asm/byteorder.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <sys/ioctl.h>
33#include <sound/asound.h>
34
35namespace android
36{
37
38static jclass sFileDescriptorClass;
39
40static jint
41android_server_UsbMidiDevice_get_subdevice_count(JNIEnv *env, jobject /* thiz */,
42        jint card, jint device)
43{
44    char    path[100];
45
46    snprintf(path, sizeof(path), "/dev/snd/controlC%d", card);
47    int fd = open(path, O_RDWR);
48    if (fd < 0) {
49        ALOGE("could not open %s", path);
50        return 0;
51    }
52
53    struct snd_rawmidi_info info;
54    memset(&info, 0, sizeof(info));
55    info.device = device;
56    int ret = ioctl(fd, SNDRV_CTL_IOCTL_RAWMIDI_INFO, &info);
57    close(fd);
58
59    if (ret < 0) {
60        ALOGE("SNDRV_CTL_IOCTL_RAWMIDI_INFO failed, errno: %d path: %s", errno, path);
61        return -1;
62    }
63
64    ALOGD("subdevices_count: %d", info.subdevices_count);
65    return info.subdevices_count;
66}
67
68static jobjectArray
69android_server_UsbMidiDevice_open(JNIEnv *env, jobject /* thiz */, jint card, jint device,
70        jint subdevice_count)
71{
72    char    path[100];
73
74    snprintf(path, sizeof(path), "/dev/snd/midiC%dD%d", card, device);
75
76    jobjectArray fds = env->NewObjectArray(subdevice_count, sFileDescriptorClass, NULL);
77    if (!fds) {
78        return NULL;
79    }
80
81    // to support multiple subdevices we open the same file multiple times
82    for (int i = 0; i < subdevice_count; i++) {
83        int fd = open(path, O_RDWR);
84        if (fd < 0) {
85            ALOGE("open failed on %s for index %d", path, i);
86            return NULL;
87        }
88
89        jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
90        env->SetObjectArrayElement(fds, i, fileDescriptor);
91        env->DeleteLocalRef(fileDescriptor);
92    }
93
94    return fds;
95}
96
97static void
98android_server_UsbMidiDevice_close(JNIEnv *env, jobject /* thiz */, jobjectArray fds)
99{
100    int count = env->GetArrayLength(fds);
101    for (int i = 0; i < count; i++) {
102        jobject fd = env->GetObjectArrayElement(fds, i);
103        close(jniGetFDFromFileDescriptor(env, fd));
104    }
105}
106
107static JNINativeMethod method_table[] = {
108    { "nativeGetSubdeviceCount", "(II)I", (void*)android_server_UsbMidiDevice_get_subdevice_count },
109    { "nativeOpen", "(III)[Ljava/io/FileDescriptor;", (void*)android_server_UsbMidiDevice_open },
110    { "nativeClose", "([Ljava/io/FileDescriptor;)V", (void*)android_server_UsbMidiDevice_close },
111};
112
113int register_android_server_UsbMidiDevice(JNIEnv *env)
114{
115    jclass clazz = env->FindClass("java/io/FileDescriptor");
116    if (clazz == NULL) {
117        ALOGE("Can't find java/io/FileDescriptor");
118        return -1;
119    }
120    sFileDescriptorClass = (jclass)env->NewGlobalRef(clazz);;
121
122    clazz = env->FindClass("com/android/server/usb/UsbMidiDevice");
123    if (clazz == NULL) {
124        ALOGE("Can't find com/android/server/usb/UsbMidiDevice");
125        return -1;
126    }
127
128    return jniRegisterNativeMethods(env, "com/android/server/usb/UsbMidiDevice",
129            method_table, NELEM(method_table));
130}
131
132};
133