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