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" 2346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 2446d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <stdio.h> 2546d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <asm/byteorder.h> 2646d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/types.h> 2746d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/stat.h> 2846d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <fcntl.h> 2946d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <sys/ioctl.h> 3046d0adf8256a42416584765625852b6e48497c90Mike Lockwood#include <linux/usb/f_accessory.h> 3146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3246d0adf8256a42416584765625852b6e48497c90Mike Lockwood#define DRIVER_NAME "/dev/usb_accessory" 3346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3446d0adf8256a42416584765625852b6e48497c90Mike Lockwoodnamespace android 3546d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 3646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 3746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic struct parcel_file_descriptor_offsets_t 3846d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 3946d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass mClass; 4046d0adf8256a42416584765625852b6e48497c90Mike Lockwood jmethodID mConstructor; 4146d0adf8256a42416584765625852b6e48497c90Mike Lockwood} gParcelFileDescriptorOffsets; 4246d0adf8256a42416584765625852b6e48497c90Mike Lockwood 4346d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 4446d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (env->ExceptionCheck()) { 453762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("An exception was thrown by callback '%s'.", methodName); 4646d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOGE_EX(env); 4746d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->ExceptionClear(); 4846d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 4946d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 5046d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5146d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index) 5246d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 5346d0adf8256a42416584765625852b6e48497c90Mike Lockwood char buffer[256]; 5446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 5546d0adf8256a42416584765625852b6e48497c90Mike Lockwood buffer[0] = 0; 5646d0adf8256a42416584765625852b6e48497c90Mike Lockwood int length = ioctl(fd, cmd, buffer); 5746d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (buffer[0]) { 5846d0adf8256a42416584765625852b6e48497c90Mike Lockwood jstring obj = env->NewStringUTF(buffer); 5946d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->SetObjectArrayElement(strArray, index, obj); 6046d0adf8256a42416584765625852b6e48497c90Mike Lockwood env->DeleteLocalRef(obj); 6146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 6246d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 6346d0adf8256a42416584765625852b6e48497c90Mike Lockwood 6446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 6546d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic jobjectArray android_server_UsbDeviceManager_getAccessoryStrings(JNIEnv *env, jobject thiz) 6646d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 6746d0adf8256a42416584765625852b6e48497c90Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 6846d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fd < 0) { 693762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 7046d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 7146d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 7246d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass stringClass = env->FindClass("java/lang/String"); 7346d0adf8256a42416584765625852b6e48497c90Mike Lockwood jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL); 7446d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (!strArray) goto out; 7546d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); 7646d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); 7746d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); 7846d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); 7946d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); 8046d0adf8256a42416584765625852b6e48497c90Mike Lockwood set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5); 8146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8246d0adf8256a42416584765625852b6e48497c90Mike Lockwoodout: 8346d0adf8256a42416584765625852b6e48497c90Mike Lockwood close(fd); 8446d0adf8256a42416584765625852b6e48497c90Mike Lockwood return strArray; 8546d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 8646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 8746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobject thiz) 8846d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 8946d0adf8256a42416584765625852b6e48497c90Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 9046d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fd < 0) { 913762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 9246d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 9346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9446d0adf8256a42416584765625852b6e48497c90Mike Lockwood jobject fileDescriptor = jniCreateFileDescriptor(env, fd); 9546d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (fileDescriptor == NULL) { 9646d0adf8256a42416584765625852b6e48497c90Mike Lockwood return NULL; 9746d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 9846d0adf8256a42416584765625852b6e48497c90Mike Lockwood return env->NewObject(gParcelFileDescriptorOffsets.mClass, 9946d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mConstructor, fileDescriptor); 10046d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 10146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 102d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwoodstatic jboolean android_server_UsbDeviceManager_isStartRequested(JNIEnv *env, jobject thiz) 103d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood{ 104d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 105d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood if (fd < 0) { 1063762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("could not open %s", DRIVER_NAME); 107d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood return false; 108d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood } 109d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood int result = ioctl(fd, ACCESSORY_IS_START_REQUESTED); 110d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood close(fd); 111d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood return (result == 1); 112d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood} 113d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 114166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwoodstatic jint android_server_UsbDeviceManager_getAudioMode(JNIEnv *env, jobject thiz) 115166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood{ 116166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood int fd = open(DRIVER_NAME, O_RDWR); 117166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood if (fd < 0) { 118166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood ALOGE("could not open %s", DRIVER_NAME); 119166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood return false; 120166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood } 121166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood int result = ioctl(fd, ACCESSORY_GET_AUDIO_MODE); 122166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood close(fd); 123166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood return result; 124166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood} 125d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood 12646d0adf8256a42416584765625852b6e48497c90Mike Lockwoodstatic JNINativeMethod method_table[] = { 12746d0adf8256a42416584765625852b6e48497c90Mike Lockwood { "nativeGetAccessoryStrings", "()[Ljava/lang/String;", 12846d0adf8256a42416584765625852b6e48497c90Mike Lockwood (void*)android_server_UsbDeviceManager_getAccessoryStrings }, 12946d0adf8256a42416584765625852b6e48497c90Mike Lockwood { "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;", 13046d0adf8256a42416584765625852b6e48497c90Mike Lockwood (void*)android_server_UsbDeviceManager_openAccessory }, 131d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood { "nativeIsStartRequested", "()Z", 132d462ecf8f82076d21c85bdeeefbd16a1a91d2805Mike Lockwood (void*)android_server_UsbDeviceManager_isStartRequested }, 133166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood { "nativeGetAudioMode", "()I", 134166b05e0ce913711d27ce1a116b3f1fd906822e4Mike Lockwood (void*)android_server_UsbDeviceManager_getAudioMode }, 13546d0adf8256a42416584765625852b6e48497c90Mike Lockwood}; 13646d0adf8256a42416584765625852b6e48497c90Mike Lockwood 13746d0adf8256a42416584765625852b6e48497c90Mike Lockwoodint register_android_server_UsbDeviceManager(JNIEnv *env) 13846d0adf8256a42416584765625852b6e48497c90Mike Lockwood{ 13946d0adf8256a42416584765625852b6e48497c90Mike Lockwood jclass clazz = env->FindClass("com/android/server/usb/UsbDeviceManager"); 14046d0adf8256a42416584765625852b6e48497c90Mike Lockwood if (clazz == NULL) { 1413762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Can't find com/android/server/usb/UsbDeviceManager"); 14246d0adf8256a42416584765625852b6e48497c90Mike Lockwood return -1; 14346d0adf8256a42416584765625852b6e48497c90Mike Lockwood } 14446d0adf8256a42416584765625852b6e48497c90Mike Lockwood 14546d0adf8256a42416584765625852b6e48497c90Mike Lockwood clazz = env->FindClass("android/os/ParcelFileDescriptor"); 14646d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 14746d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 14846d0adf8256a42416584765625852b6e48497c90Mike Lockwood gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 14946d0adf8256a42416584765625852b6e48497c90Mike Lockwood LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, 15046d0adf8256a42416584765625852b6e48497c90Mike Lockwood "Unable to find constructor for android.os.ParcelFileDescriptor"); 15146d0adf8256a42416584765625852b6e48497c90Mike Lockwood 15246d0adf8256a42416584765625852b6e48497c90Mike Lockwood return jniRegisterNativeMethods(env, "com/android/server/usb/UsbDeviceManager", 15346d0adf8256a42416584765625852b6e48497c90Mike Lockwood method_table, NELEM(method_table)); 15446d0adf8256a42416584765625852b6e48497c90Mike Lockwood} 15546d0adf8256a42416584765625852b6e48497c90Mike Lockwood 15646d0adf8256a42416584765625852b6e48497c90Mike Lockwood}; 157