/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "UsbService" #include "utils/Log.h" #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include "utils/Vector.h" #include #include #include #include #include #include #include #define DRIVER_NAME "/dev/usb_accessory" namespace android { static struct file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; jfieldID mDescriptor; } gFileDescriptorOffsets; static struct parcel_file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; } gParcelFileDescriptorOffsets; static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { LOGE("An exception was thrown by callback '%s'.", methodName); LOGE_EX(env); env->ExceptionClear(); } } static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) { char buffer[256]; buffer[0] = 0; int length = ioctl(fd, cmd, buffer); if (buffer[0]) { jstring obj = env->NewStringUTF(buffer); env->SetObjectArrayElement(strArray, index, obj); env->DeleteLocalRef(obj); } } static jobjectArray android_server_UsbService_getAccessoryStrings(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { LOGE("could not open %s", DRIVER_NAME); return NULL; } jclass stringClass = env->FindClass("java/lang/String"); jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL); if (!strArray) goto out; set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5); out: close(fd); return strArray; } static jobject android_server_UsbService_openAccessory(JNIEnv *env, jobject thiz) { int fd = open(DRIVER_NAME, O_RDWR); if (fd < 0) { LOGE("could not open %s", DRIVER_NAME); return NULL; } jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); if (fileDescriptor != NULL) { env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, fd); } else { return NULL; } return env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); } static JNINativeMethod method_table[] = { { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", (void*)android_server_UsbService_getAccessoryStrings }, { "nativeOpenAccessory","()Landroid/os/ParcelFileDescriptor;", (void*)android_server_UsbService_openAccessory }, }; int register_android_server_UsbService(JNIEnv *env) { jclass clazz = env->FindClass("java/io/FileDescriptor"); LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "", "()V"); gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, "Unable to find descriptor field in java.io.FileDescriptor"); clazz = env->FindClass("android/os/ParcelFileDescriptor"); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "", "(Ljava/io/FileDescriptor;)V"); LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, "Unable to find constructor for android.os.ParcelFileDescriptor"); return jniRegisterNativeMethods(env, "com/android/server/usb/UsbService", method_table, NELEM(method_table)); } };