wifi.c revision ed8487244b1c9f72fb5d22c7a18918ac34063cee
1cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/*
2cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Copyright 2008, The Android Open Source Project
3cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
4cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * you may not use this file except in compliance with the License.
6cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * You may obtain a copy of the License at
7cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
8cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
10cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * See the License for the specific language governing permissions and
14cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * limitations under the License.
15cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project */
16cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
17cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <stdlib.h>
18cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <fcntl.h>
19cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <errno.h>
20cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <string.h>
21cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
22cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "hardware_legacy/wifi.h"
23cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "libwpa_client/wpa_ctrl.h"
24cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
25cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define LOG_TAG "WifiHW"
26cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/log.h"
27cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/memory.h"
28cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/misc.h"
29cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/properties.h"
30cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "private/android_filesystem_config.h"
31cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
32cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
33cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <sys/_system_properties.h>
34cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#endif
35cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
36cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic struct wpa_ctrl *ctrl_conn;
37cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic struct wpa_ctrl *monitor_conn;
38cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
39cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int do_dhcp();
40cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int ifc_init();
41cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern void ifc_close();
42cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern char *dhcp_lasterror();
43cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern void get_dhcp_info();
44cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int init_module(void *, unsigned long, const char *);
45cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int delete_module(const char *, unsigned int);
46cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
47cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic char iface[PROPERTY_VALUE_MAX];
48cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
49cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project// sockets is in
50cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
51243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_DRIVER_MODULE_PATH
52243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_DRIVER_MODULE_PATH         "/system/lib/modules/wlan.ko"
53243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
54243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_DRIVER_MODULE_NAME
55243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_DRIVER_MODULE_NAME         "wlan"
56243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
57243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_DRIVER_MODULE_ARG
58243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_DRIVER_MODULE_ARG          ""
59243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
60243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_FIRMWARE_LOADER
61243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_FIRMWARE_LOADER		""
62243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
63243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_TEST_INTERFACE		"sta"
64243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt
65ed8487244b1c9f72fb5d22c7a18918ac34063ceeDmitry Shmidt#define WIFI_DRIVER_LOADER_DELAY	1000000
66ed8487244b1c9f72fb5d22c7a18918ac34063ceeDmitry Shmidt
67cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char IFACE_DIR[]           = "/data/system/wpa_supplicant";
68243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_NAME[]  = WIFI_DRIVER_MODULE_NAME;
69243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_TAG[]   = WIFI_DRIVER_MODULE_NAME " ";
70243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_PATH[]  = WIFI_DRIVER_MODULE_PATH;
71243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_ARG[]   = WIFI_DRIVER_MODULE_ARG;
72243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char FIRMWARE_LOADER[]     = WIFI_FIRMWARE_LOADER;
73cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char DRIVER_PROP_NAME[]    = "wlan.driver.status";
74cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPPLICANT_NAME[]     = "wpa_supplicant";
75cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_PROP_NAME[]      = "init.svc.wpa_supplicant";
76cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
77cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";
78cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char MODULE_FILE[]         = "/proc/modules";
79cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
80243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic int insmod(const char *filename, const char *args)
81cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
82cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    void *module;
83cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    unsigned int size;
84cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret;
85cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
86cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    module = load_file(filename, &size);
87cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!module)
88cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
89cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
90243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    ret = init_module(module, size, args);
91cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
92cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    free(module);
93cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
94cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return ret;
95cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
96cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
97cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int rmmod(const char *modname)
98cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
99cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret = -1;
100cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int maxtry = 10;
101cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
102cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (maxtry-- > 0) {
103cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ret = delete_module(modname, O_NONBLOCK | O_EXCL);
104cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (ret < 0 && errno == EAGAIN)
105cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            usleep(500000);
106cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        else
107cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            break;
108cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
109cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
110cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret != 0)
111cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGD("Unable to unload driver module \"%s\": %s\n",
112cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project             modname, strerror(errno));
113cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return ret;
114cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
115cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
116cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint do_dhcp_request(int *ipaddr, int *gateway, int *mask,
117cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                    int *dns1, int *dns2, int *server, int *lease) {
118cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* For test driver, always report success */
119243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    if (strcmp(iface, WIFI_TEST_INTERFACE) == 0)
120cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
121cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
122cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ifc_init() < 0)
123cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
124cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
125cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (do_dhcp(iface) < 0) {
126cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ifc_close();
127cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
128cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
129cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    ifc_close();
130cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
131cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
132cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
133cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
134cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectconst char *get_dhcp_error_string() {
135cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return dhcp_lasterror();
136cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
137cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
138cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int check_driver_loaded() {
139cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char driver_status[PROPERTY_VALUE_MAX];
140cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    FILE *proc;
141cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char line[sizeof(DRIVER_MODULE_TAG)+10];
142cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
143cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
144cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            || strcmp(driver_status, "ok") != 0) {
145cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;  /* driver not loaded */
146cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
147cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
148cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * If the property says the driver is loaded, check to
149cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * make sure that the property setting isn't just left
150cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * over from a previous manual shutdown or a runtime
151cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * crash.
152cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
153cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
154cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
155243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set(DRIVER_PROP_NAME, "unloaded");
156cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
157cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
158cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while ((fgets(line, sizeof(line), proc)) != NULL) {
159cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
160cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            fclose(proc);
161cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            return 1;
162cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
163cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
164cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fclose(proc);
165cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set(DRIVER_PROP_NAME, "unloaded");
166cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
167cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
168cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
169cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_load_driver()
170cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
171cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char driver_status[PROPERTY_VALUE_MAX];
172cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 100; /* wait at most 20 seconds for completion */
173cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
174cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (check_driver_loaded()) {
175cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
176cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
177cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
178243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
179cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
180243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt
181243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    if (strcmp(FIRMWARE_LOADER,"") == 0) {
182ed8487244b1c9f72fb5d22c7a18918ac34063ceeDmitry Shmidt        usleep(WIFI_DRIVER_LOADER_DELAY);
183243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set(DRIVER_PROP_NAME, "ok");
184243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    }
185243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    else {
186243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set("ctl.start", FIRMWARE_LOADER);
187243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    }
188cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
189cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
190cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
191cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(driver_status, "ok") == 0)
192cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
1937b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt            else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
1947b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt                wifi_unload_driver();
195cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return -1;
1967b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt            }
197cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
198cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(200000);
199cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
200cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set(DRIVER_PROP_NAME, "timeout");
2017b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt    wifi_unload_driver();
202cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
203cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
204cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
205cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_unload_driver()
206cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
207cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 20; /* wait at most 10 seconds for completion */
208243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt
209cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (rmmod(DRIVER_MODULE_NAME) == 0) {
210cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	while (count-- > 0) {
211cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	    if (!check_driver_loaded())
212cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project		break;
213cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    	    usleep(500000);
214cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	}
215cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	if (count) {
216cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    	    return 0;
217cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	}
218cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project	return -1;
219cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else
220cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
221cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
222cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
223cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint ensure_config_file_exists()
224cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
225cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char buf[2048];
226cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int srcfd, destfd;
227cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int nread;
228cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
229cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (access(SUPP_CONFIG_FILE, R_OK|W_OK) == 0) {
230cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
231cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else if (errno != ENOENT) {
232cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Cannot access \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
233cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
234cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
235cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
236cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY);
237cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (srcfd < 0) {
238cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
239cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
240cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
241cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
242cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_WRONLY, 0660);
243cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (destfd < 0) {
244cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        close(srcfd);
245cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Cannot create \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
246cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
247cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
248cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
249cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while ((nread = read(srcfd, buf, sizeof(buf))) != 0) {
250cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (nread < 0) {
251cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
252cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            close(srcfd);
253cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            close(destfd);
254cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            unlink(SUPP_CONFIG_FILE);
255cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            return -1;
256cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
257cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        write(destfd, buf, nread);
258cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
259cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
260cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(destfd);
261cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(srcfd);
262cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
263cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) {
264cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Error changing group ownership of %s to %d: %s",
265cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project             SUPP_CONFIG_FILE, AID_WIFI, strerror(errno));
266cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        unlink(SUPP_CONFIG_FILE);
267cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
268cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
269cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
270cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
271cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
272cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_start_supplicant()
273cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
274cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
275cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 200; /* wait at most 20 seconds for completion */
276cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
277cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    const prop_info *pi;
278cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    unsigned serial = 0;
279cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#endif
280cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
281cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check whether already running */
282cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (property_get(SUPP_PROP_NAME, supp_status, NULL)
283cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            && strcmp(supp_status, "running") == 0) {
284cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
285cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
286cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
287cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Before starting the daemon, make sure its config file exists */
288cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ensure_config_file_exists() < 0) {
289cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Wi-Fi will not be enabled");
290cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
291cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
292cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
293cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Clear out any stale socket files that might be left over. */
294cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    wpa_ctrl_cleanup();
295cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
296cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
297cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
298cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * Get a reference to the status property, so we can distinguish
299cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * the case where it goes stopped => running => stopped (i.e.,
300cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * it start up, but fails right away) from the case in which
301cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * it starts in the stopped state and never manages to start
302cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * running at all.
303cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
304cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    pi = __system_property_find(SUPP_PROP_NAME);
305cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (pi != NULL) {
306cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        serial = pi->serial;
307cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
308cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#endif
309cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set("ctl.start", SUPPLICANT_NAME);
310cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
311cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
312cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
313007404c68f5cf6328e30b6d0edac3fd52ef36abbDmitry Shmidt#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
314cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (pi == NULL) {
315cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            pi = __system_property_find(SUPP_PROP_NAME);
316cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
317cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (pi != NULL) {
318cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            __system_property_read(pi, NULL, supp_status);
319cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(supp_status, "running") == 0) {
320cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
321cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            } else if (pi->serial != serial &&
322cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                    strcmp(supp_status, "stopped") == 0) {
323cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return -1;
324cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            }
325cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
326cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#else
327cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
328cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(supp_status, "running") == 0)
329cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
330cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
331cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#endif
332cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(100000);
333cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
334cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
335cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
336cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
337cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_stop_supplicant()
338cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
339cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
340cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 50; /* wait at most 5 seconds for completion */
341cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
342cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check whether supplicant already stopped */
343cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (property_get(SUPP_PROP_NAME, supp_status, NULL)
344cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        && strcmp(supp_status, "stopped") == 0) {
345cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
346cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
347cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
348cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set("ctl.stop", SUPPLICANT_NAME);
349cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
350cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
351cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
352cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
353cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(supp_status, "stopped") == 0)
354cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
355cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
356cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(100000);
357cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
358cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
359cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
360cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
361cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_connect_to_supplicant()
362cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
363cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char ifname[256];
364cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
365cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
366cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Make sure supplicant is running */
367cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!property_get(SUPP_PROP_NAME, supp_status, NULL)
368cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            || strcmp(supp_status, "running") != 0) {
369cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Supplicant not running, cannot connect");
370cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
371cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
372cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
373243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    property_get("wifi.interface", iface, WIFI_TEST_INTERFACE);
374cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
375cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (access(IFACE_DIR, F_OK) == 0) {
376cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        snprintf(ifname, sizeof(ifname), "%s/%s", IFACE_DIR, iface);
377cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else {
378cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        strlcpy(ifname, iface, sizeof(ifname));
379cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
380cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
381cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    ctrl_conn = wpa_ctrl_open(ifname);
382cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ctrl_conn == NULL) {
383cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGE("Unable to open connection to supplicant on \"%s\": %s",
384cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project             ifname, strerror(errno));
385cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
386cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
387cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    monitor_conn = wpa_ctrl_open(ifname);
388cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (monitor_conn == NULL) {
389cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        wpa_ctrl_close(ctrl_conn);
390cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ctrl_conn = NULL;
391cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
392cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
393cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (wpa_ctrl_attach(monitor_conn) != 0) {
394cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        wpa_ctrl_close(monitor_conn);
395cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        wpa_ctrl_close(ctrl_conn);
396cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ctrl_conn = monitor_conn = NULL;
397cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
398cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
399cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
400cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
401cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
402cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
403cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
404cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret;
405cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
406cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ctrl_conn == NULL) {
407cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
408cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
409cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
410cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
411cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret == -2) {
412cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGD("'%s' command timed out.\n", cmd);
413cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -2;
414cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
415cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
416cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
417cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (strncmp(cmd, "PING", 4) == 0) {
418cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        reply[*reply_len] = '\0';
419cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
420cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
421cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
422cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
423cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_wait_for_event(char *buf, size_t buflen)
424cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
425cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    size_t nread = buflen - 1;
426cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int fd;
427cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fd_set rfds;
428cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int result;
429cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    struct timeval tval;
430cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    struct timeval *tptr;
431cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
4322631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff    if (monitor_conn == NULL) {
433007404c68f5cf6328e30b6d0edac3fd52ef36abbDmitry Shmidt        LOGD("Connection closed\n");
4342631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1);
4352631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        buf[buflen-1] = '\0';
4362631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        return strlen(buf);
4372631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff    }
438cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
439cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    result = wpa_ctrl_recv(monitor_conn, buf, &nread);
440cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (result < 0) {
441cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGD("wpa_ctrl_recv failed: %s\n", strerror(errno));
4422631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        strncpy(buf, WPA_EVENT_TERMINATING " - recv error", buflen-1);
4432631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        buf[buflen-1] = '\0';
4442631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff        return strlen(buf);
445cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
446cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    buf[nread] = '\0';
447cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* LOGD("wait_for_event: result=%d nread=%d string=\"%s\"\n", result, nread, buf); */
448cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check for EOF on the socket */
449cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (result == 0 && nread == 0) {
450cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        /* Fabricate an event to pass up */
451cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        LOGD("Received EOF on supplicant socket\n");
452cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        strncpy(buf, WPA_EVENT_TERMINATING " - signal 0 received", buflen-1);
453cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        buf[buflen-1] = '\0';
454cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return strlen(buf);
455cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
456cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
457cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * Events strings are in the format
458cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *
459cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *     <N>CTRL-EVENT-XXX
460cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *
461cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
462cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * etc.) and XXX is the event name. The level information is not useful
463cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * to us, so strip it off.
464cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
465cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (buf[0] == '<') {
466cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        char *match = strchr(buf, '>');
467cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (match != NULL) {
468cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            nread -= (match+1-buf);
469cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            memmove(buf, match+1, nread+1);
470cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
471cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
472cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return nread;
473cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
474cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
475cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectvoid wifi_close_supplicant_connection()
476cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
477cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ctrl_conn != NULL) {
478cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        wpa_ctrl_close(ctrl_conn);
479cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ctrl_conn = NULL;
480cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
481cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (monitor_conn != NULL) {
482cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        wpa_ctrl_close(monitor_conn);
483cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        monitor_conn = NULL;
484cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
485cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
486cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
487cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_command(const char *command, char *reply, size_t *reply_len)
488cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
489cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return wifi_send_command(ctrl_conn, command, reply, reply_len);
490cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
491