146d0adf8256a42416584765625852b6e48497c90Mike Lockwood/* 246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 546d0adf8256a42416584765625852b6e48497c90Mike Lockwood * you may not use this file except in compliance with the License. 646d0adf8256a42416584765625852b6e48497c90Mike Lockwood * You may obtain a copy of the License at 746d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 846d0adf8256a42416584765625852b6e48497c90Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 946d0adf8256a42416584765625852b6e48497c90Mike Lockwood * 1046d0adf8256a42416584765625852b6e48497c90Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1146d0adf8256a42416584765625852b6e48497c90Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1246d0adf8256a42416584765625852b6e48497c90Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346d0adf8256a42416584765625852b6e48497c90Mike Lockwood * See the License for the specific language governing permissions and 1446d0adf8256a42416584765625852b6e48497c90Mike Lockwood * limitations under the License. 1546d0adf8256a42416584765625852b6e48497c90Mike Lockwood */ 1646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 1746d0adf8256a42416584765625852b6e48497c90Mike Lockwood#define LOG_TAG "UsbDeviceManagerJNI" 1846d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include "utils/Log.h" 1946d0adf8256a42416584765625852b6e48497c90Mike Lockwood 2046d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include "jni.h" 2146d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include "JNIHelp.h" 2246d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include "android_runtime/AndroidRuntime.h" 2387eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include "android_runtime/Log.h" 2446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 2546d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <stdio.h> 2646d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <asm/byteorder.h> 2746d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/types.h> 2846d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/stat.h> 2946d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <fcntl.h> 3046d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/ioctl.h> 3146d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <linux/usb/f_accessory.h> 3246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3346d0adf8256a42416584765625852b6e48497c90Mike Lockwood#define DRIVER_NAME "/dev/usb_accessory" 3446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodnamespace android 3646d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 3746d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic struct parcel_file_descriptor_offsets_t 3946d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 4046d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass mClass; 4146d0adf8256a42416584765625852b6e48497c90Mike Lockwood jmethodID mConstructor; 4246d0adf8256a42416584765625852b6e48497c90Mike Lockwood} gParcelFileDescriptorOffsets; 4346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 4446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 4546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (env->ExceptionCheck()) { 463762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("An exception was thrown by callback '%s'.", methodName); 4746d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOGE_EX(env); 4846d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->ExceptionClear(); 4946d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 5146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) 5346d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 5446d0adf8256a42416584765625852b6e48497c90Mike Lockwood char buffer[256]; 5546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5646d0adf8256a42416584765625852b6e48497c90Mike Lockwood buffer[0] = 0; 5746d0adf8256a42416584765625852b6e48497c90Mike Lockwood int length = ioctl(fd, cmd, buffer); 5846d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (buffer[0]) { 5946d0adf8256a42416584765625852b6e48497c90Mike Lockwood jstring obj = env->NewStringUTF(buffer); 6046d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->SetObjectArrayElement(strArray, index, obj); 6146d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->DeleteLocalRef(obj); 6246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 6346d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 6446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 6546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 6646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic jobjectArray android_server_UsbDeviceManager_getAccessoryStrings(JNIEnv *env, jobject thiz) 6746d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 6846d0adf8256a42416584765625852b6e48497c90Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 6946d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fd < 0) { 703762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 7146d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 7246d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 7346d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass stringClass = env->FindClass("java/lang/String"); 7446d0adf8256a42416584765625852b6e48497c90Mike Lockwood jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL); 7546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (!strArray) goto out; 7646d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); 7746d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); 7846d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); 7946d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); 8046d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); 8146d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5); 8246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodout: 8446d0adf8256a42416584765625852b6e48497c90Mike Lockwood close(fd); 8546d0adf8256a42416584765625852b6e48497c90Mike Lockwood return strArray; 8646d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 8746d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobject thiz) 8946d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 9046d0adf8256a42416584765625852b6e48497c90Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 9146d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fd < 0) { 923762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 9346d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 9446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9546d0adf8256a42416584765625852b6e48497c90Mike Lockwood jobject fileDescriptor = jniCreateFileDescriptor(env, fd); 9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fileDescriptor == NULL) { 9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9946d0adf8256a42416584765625852b6e48497c90Mike Lockwood return env->NewObject(gParcelFileDescriptorOffsets.mClass, 10046d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); 10146d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 10246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 103d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwoodstatic jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz) 104d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood{ 105d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 106d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (fd < 0) { 1073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 108d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood return false; 109d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood } 110d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED); 111d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood close(fd); 112d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood return (result == 1); 113d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood} 114d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 115166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwoodstatic jint android_server_UsbDeviceManager_getAudioMode(JNIEnv *env, jobject thiz) 116166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood{ 117166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 118166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood if (fd < 0) { 119166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood ALOGE("could not open %s", DRIVER_NAME); 120166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood return false; 121166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood } 122166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood int result = ioctl(fd, ACCESSORY_GET_AUDIO_MODE); 123166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood close(fd); 124166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood return result; 125166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood} 126d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 12746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic JNINativeMethod method_table[] = { 12846d0adf8256a42416584765625852b6e48497c90Mike Lockwood { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", 12946d0adf8256a42416584765625852b6e48497c90Mike Lockwood (void*)android_server_UsbDeviceManager_getAccessoryStrings }, 13046d0adf8256a42416584765625852b6e48497c90Mike Lockwood { "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;", 13146d0adf8256a42416584765625852b6e48497c90Mike Lockwood (void*)android_server_UsbDeviceManager_openAccessory }, 132d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood { "nativeIsStartRequested", "()Z", 133d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood (void*)android_server_UsbDeviceManager_isStartRequested }, 134166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood { "nativeGetAudioMode", "()I", 135166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood (void*)android_server_UsbDeviceManager_getAudioMode }, 13646d0adf8256a42416584765625852b6e48497c90Mike Lockwood}; 13746d0adf8256a42416584765625852b6e48497c90Mike Lockwood 13846d0adf8256a42416584765625852b6e48497c90Mike Lockwoodint register_android_server_UsbDeviceManager(JNIEnv *env) 13946d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass clazz = env->FindClass("com/android/server/usb/UsbDeviceManager"); 14146d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (clazz == NULL) { 1423762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find com/android/server/usb/UsbDeviceManager"); 14346d0adf8256a42416584765625852b6e48497c90Mike Lockwood return -1; 14446d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 14546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 14646d0adf8256a42416584765625852b6e48497c90Mike Lockwood clazz = env->FindClass("android/os/ParcelFileDescriptor"); 14746d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 14846d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 14946d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 15046d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, 15146d0adf8256a42416584765625852b6e48497c90Mike Lockwood "Unable to find constructor for android.os.ParcelFileDescriptor"); 15246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 15346d0adf8256a42416584765625852b6e48497c90Mike Lockwood return jniRegisterNativeMethods(env, "com/android/server/usb/UsbDeviceManager", 15446d0adf8256a42416584765625852b6e48497c90Mike Lockwood method_table, NELEM(method_table)); 15546d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 15646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 15746d0adf8256a42416584765625852b6e48497c90Mike Lockwood}; 158