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