android_net_wifi_Wifi.cpp revision 7d6d9c005e5cfad787bb62b7fee6be2d75b13ca3
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, jboolean p2pSupported)
120{
121    return (jboolean)(::wifi_start_supplicant(p2pSupported) == 0);
122}
123
124static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
125{
126    return (jboolean)(::wifi_stop_supplicant() == 0);
127}
128
129static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface)
130{
131    ScopedUtfChars ifname(env, jIface);
132    return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0);
133}
134
135static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface)
136{
137    ScopedUtfChars ifname(env, jIface);
138    ::wifi_close_supplicant_connection(ifname.c_str());
139}
140
141static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface)
142{
143    char buf[BUF_SIZE];
144    ScopedUtfChars ifname(env, jIface);
145    int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf);
146    if (nread > 0) {
147        return env->NewStringUTF(buf);
148    } else {
149        return NULL;
150    }
151}
152
153static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface,
154        jstring jCommand)
155{
156    ScopedUtfChars ifname(env, jIface);
157    ScopedUtfChars command(env, jCommand);
158
159    if (command.c_str() == NULL) {
160        return JNI_FALSE;
161    }
162    if (DBG) ALOGD("doBoolean: %s", command.c_str());
163    return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str());
164}
165
166static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface,
167        jstring jCommand)
168{
169    ScopedUtfChars ifname(env, jIface);
170    ScopedUtfChars command(env, jCommand);
171
172    if (command.c_str() == NULL) {
173        return -1;
174    }
175    if (DBG) ALOGD("doInt: %s", command.c_str());
176    return doIntCommand(ifname.c_str(), "%s", command.c_str());
177}
178
179static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface,
180        jstring jCommand)
181{
182    ScopedUtfChars ifname(env, jIface);
183
184    ScopedUtfChars command(env, jCommand);
185    if (command.c_str() == NULL) {
186        return NULL;
187    }
188    if (DBG) ALOGD("doString: %s", command.c_str());
189    return doStringCommand(env, ifname.c_str(), "%s", command.c_str());
190}
191
192
193
194// ----------------------------------------------------------------------------
195
196/*
197 * JNI registration.
198 */
199static JNINativeMethod gWifiMethods[] = {
200    /* name, signature, funcPtr */
201
202    { "loadDriver", "()Z",  (void *)android_net_wifi_loadDriver },
203    { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded },
204    { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
205    { "startSupplicant", "(Z)Z",  (void *)android_net_wifi_startSupplicant },
206    { "killSupplicant", "()Z",  (void *)android_net_wifi_killSupplicant },
207    { "connectToSupplicant", "(Ljava/lang/String;)Z",
208            (void *)android_net_wifi_connectToSupplicant },
209    { "closeSupplicantConnection", "(Ljava/lang/String;)V",
210            (void *)android_net_wifi_closeSupplicantConnection },
211    { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;",
212            (void*) android_net_wifi_waitForEvent },
213    { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z",
214            (void*) android_net_wifi_doBooleanCommand },
215    { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I",
216            (void*) android_net_wifi_doIntCommand },
217    { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
218            (void*) android_net_wifi_doStringCommand },
219};
220
221int register_android_net_wifi_WifiManager(JNIEnv* env)
222{
223    return AndroidRuntime::registerNativeMethods(env,
224            WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
225}
226
227}; // namespace android
228