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 WIFI_PKG_NAME "android/net/wifi/WifiNative" 29#define BUF_SIZE 256 30#define EVENT_BUF_SIZE 2048 31 32namespace android { 33 34static jint DBG = false; 35 36static int doCommand(const char *ifname, const char *cmd, char *replybuf, int replybuflen) 37{ 38 size_t reply_len = replybuflen - 1; 39 40 if (::wifi_command(ifname, cmd, replybuf, &reply_len) != 0) 41 return -1; 42 else { 43 // Strip off trailing newline 44 if (reply_len > 0 && replybuf[reply_len-1] == '\n') 45 replybuf[reply_len-1] = '\0'; 46 else 47 replybuf[reply_len] = '\0'; 48 return 0; 49 } 50} 51 52static jint doIntCommand(const char *ifname, const char* fmt, ...) 53{ 54 char buf[BUF_SIZE]; 55 va_list args; 56 va_start(args, fmt); 57 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 58 va_end(args); 59 if (byteCount < 0 || byteCount >= BUF_SIZE) { 60 return -1; 61 } 62 char reply[BUF_SIZE]; 63 if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { 64 return -1; 65 } 66 return static_cast<jint>(atoi(reply)); 67} 68 69static jboolean doBooleanCommand(const char *ifname, const char* expect, const char* fmt, ...) 70{ 71 char buf[BUF_SIZE]; 72 va_list args; 73 va_start(args, fmt); 74 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 75 va_end(args); 76 if (byteCount < 0 || byteCount >= BUF_SIZE) { 77 return JNI_FALSE; 78 } 79 char reply[BUF_SIZE]; 80 if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { 81 return JNI_FALSE; 82 } 83 return (strcmp(reply, expect) == 0); 84} 85 86// Send a command to the supplicant, and return the reply as a String 87static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, ...) { 88 char buf[BUF_SIZE]; 89 va_list args; 90 va_start(args, fmt); 91 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 92 va_end(args); 93 if (byteCount < 0 || byteCount >= BUF_SIZE) { 94 return NULL; 95 } 96 char reply[4096]; 97 if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { 98 return NULL; 99 } 100 // TODO: why not just NewStringUTF? 101 String16 str((char *)reply); 102 return env->NewString((const jchar *)str.string(), str.size()); 103} 104 105static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject) 106{ 107 return (jboolean)(::is_wifi_driver_loaded() == 1); 108} 109 110static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) 111{ 112 return (jboolean)(::wifi_load_driver() == 0); 113} 114 115static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject) 116{ 117 return (jboolean)(::wifi_unload_driver() == 0); 118} 119 120static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) 121{ 122 return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0); 123} 124 125static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject) 126{ 127 return (jboolean)(::wifi_stop_supplicant() == 0); 128} 129 130static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface) 131{ 132 ScopedUtfChars ifname(env, jIface); 133 return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0); 134} 135 136static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface) 137{ 138 ScopedUtfChars ifname(env, jIface); 139 ::wifi_close_supplicant_connection(ifname.c_str()); 140} 141 142static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface) 143{ 144 char buf[EVENT_BUF_SIZE]; 145 ScopedUtfChars ifname(env, jIface); 146 int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf); 147 if (nread > 0) { 148 return env->NewStringUTF(buf); 149 } else { 150 return NULL; 151 } 152} 153 154static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface, 155 jstring jCommand) 156{ 157 ScopedUtfChars ifname(env, jIface); 158 ScopedUtfChars command(env, jCommand); 159 160 if (command.c_str() == NULL) { 161 return JNI_FALSE; 162 } 163 if (DBG) ALOGD("doBoolean: %s", command.c_str()); 164 return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str()); 165} 166 167static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface, 168 jstring jCommand) 169{ 170 ScopedUtfChars ifname(env, jIface); 171 ScopedUtfChars command(env, jCommand); 172 173 if (command.c_str() == NULL) { 174 return -1; 175 } 176 if (DBG) ALOGD("doInt: %s", command.c_str()); 177 return doIntCommand(ifname.c_str(), "%s", command.c_str()); 178} 179 180static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface, 181 jstring jCommand) 182{ 183 ScopedUtfChars ifname(env, jIface); 184 185 ScopedUtfChars command(env, jCommand); 186 if (command.c_str() == NULL) { 187 return NULL; 188 } 189 if (DBG) ALOGD("doString: %s", command.c_str()); 190 return doStringCommand(env, ifname.c_str(), "%s", command.c_str()); 191} 192 193 194 195// ---------------------------------------------------------------------------- 196 197/* 198 * JNI registration. 199 */ 200static JNINativeMethod gWifiMethods[] = { 201 /* name, signature, funcPtr */ 202 203 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver }, 204 { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded }, 205 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, 206 { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, 207 { "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant }, 208 { "connectToSupplicant", "(Ljava/lang/String;)Z", 209 (void *)android_net_wifi_connectToSupplicant }, 210 { "closeSupplicantConnection", "(Ljava/lang/String;)V", 211 (void *)android_net_wifi_closeSupplicantConnection }, 212 { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;", 213 (void*) android_net_wifi_waitForEvent }, 214 { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z", 215 (void*) android_net_wifi_doBooleanCommand }, 216 { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I", 217 (void*) android_net_wifi_doIntCommand }, 218 { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", 219 (void*) android_net_wifi_doStringCommand }, 220}; 221 222int register_android_net_wifi_WifiManager(JNIEnv* env) 223{ 224 return AndroidRuntime::registerNativeMethods(env, 225 WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods)); 226} 227 228}; // namespace android 229