1 /* 2 * Copyright 2008, 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 "wifi" 18 19 #include "jni.h" 20 #include <ScopedUtfChars.h> 21 #include <utils/misc.h> 22 #include <android_runtime/AndroidRuntime.h> 23 #include <utils/Log.h> 24 #include <utils/String16.h> 25 26 #include "wifi.h" 27 28 #define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size. 29 #define EVENT_BUF_SIZE 2048 30 31 namespace android { 32 33 static jint DBG = false; 34 35 static bool doCommand(JNIEnv* env, jstring javaCommand, 36 char* reply, size_t reply_len) { 37 ScopedUtfChars command(env, javaCommand); 38 if (command.c_str() == NULL) { 39 return false; // ScopedUtfChars already threw on error. 40 } 41 42 if (DBG) { 43 ALOGD("doCommand: %s", command.c_str()); 44 } 45 46 --reply_len; // Ensure we have room to add NUL termination. 47 if (::wifi_command(command.c_str(), reply, &reply_len) != 0) { 48 return false; 49 } 50 51 // Strip off trailing newline. 52 if (reply_len > 0 && reply[reply_len-1] == '\n') { 53 reply[reply_len-1] = '\0'; 54 } else { 55 reply[reply_len] = '\0'; 56 } 57 return true; 58 } 59 60 static jint doIntCommand(JNIEnv* env, jstring javaCommand) { 61 char reply[REPLY_BUF_SIZE]; 62 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 63 return -1; 64 } 65 return static_cast<jint>(atoi(reply)); 66 } 67 68 static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) { 69 char reply[REPLY_BUF_SIZE]; 70 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 71 return JNI_FALSE; 72 } 73 return (strcmp(reply, "OK") == 0); 74 } 75 76 // Send a command to the supplicant, and return the reply as a String. 77 static jstring doStringCommand(JNIEnv* env, jstring javaCommand) { 78 char reply[REPLY_BUF_SIZE]; 79 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 80 return NULL; 81 } 82 return env->NewStringUTF(reply); 83 } 84 85 static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject) 86 { 87 return (::is_wifi_driver_loaded() == 1); 88 } 89 90 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) 91 { 92 return (::wifi_load_driver() == 0); 93 } 94 95 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject) 96 { 97 return (::wifi_unload_driver() == 0); 98 } 99 100 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) 101 { 102 return (::wifi_start_supplicant(p2pSupported) == 0); 103 } 104 105 static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) 106 { 107 return (::wifi_stop_supplicant(p2pSupported) == 0); 108 } 109 110 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject) 111 { 112 return (::wifi_connect_to_supplicant() == 0); 113 } 114 115 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject) 116 { 117 ::wifi_close_supplicant_connection(); 118 } 119 120 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject) 121 { 122 char buf[EVENT_BUF_SIZE]; 123 int nread = ::wifi_wait_for_event(buf, sizeof buf); 124 if (nread > 0) { 125 return env->NewStringUTF(buf); 126 } else { 127 return NULL; 128 } 129 } 130 131 static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) { 132 return doBooleanCommand(env, javaCommand); 133 } 134 135 static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) { 136 return doIntCommand(env, javaCommand); 137 } 138 139 static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) { 140 return doStringCommand(env,javaCommand); 141 } 142 143 144 145 // ---------------------------------------------------------------------------- 146 147 /* 148 * JNI registration. 149 */ 150 static JNINativeMethod gWifiMethods[] = { 151 /* name, signature, funcPtr */ 152 153 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver }, 154 { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded }, 155 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, 156 { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, 157 { "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant }, 158 { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant }, 159 { "closeSupplicantConnectionNative", "()V", 160 (void *)android_net_wifi_closeSupplicantConnection }, 161 { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent }, 162 { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand }, 163 { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand }, 164 { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;", 165 (void*) android_net_wifi_doStringCommand }, 166 }; 167 168 int register_android_net_wifi_WifiNative(JNIEnv* env) { 169 return AndroidRuntime::registerNativeMethods(env, 170 "android/net/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods)); 171 } 172 173 }; // namespace android 174