1c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt/*
2c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * Driver interaction with extended Linux Wireless Extensions
3c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt *
4c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * This program is free software; you can redistribute it and/or modify
5c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
6c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * published by the Free Software Foundation.
7c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt *
8c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
9c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * license.
10c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt *
11c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt */
12c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
13c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "includes.h"
14c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include <sys/ioctl.h>
15c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include <net/if_arp.h>
16c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include <net/if.h>
17c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
18c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "wireless_copy.h"
19c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "common.h"
20c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "driver.h"
21c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "eloop.h"
22c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "priv_netlink.h"
23c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "driver_wext.h"
24c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "ieee802_11_defs.h"
25c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "wpa_common.h"
26c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "wpa_ctrl.h"
27c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "wpa_supplicant_i.h"
28c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "config.h"
29c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "linux_ioctl.h"
30c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "scan.h"
31c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
32c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt#include "driver_cmd_wext.h"
33c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
34c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt/**
35c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * wpa_driver_wext_set_scan_timeout - Set scan timeout to report scan completion
36c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * @priv:  Pointer to private wext data from wpa_driver_wext_init()
37c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt *
38c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * This function can be used to set registered timeout when starting a scan to
39c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * generate a scan completed event if the driver does not report this.
40c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt */
41c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtstatic void wpa_driver_wext_set_scan_timeout(void *priv)
42c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
43c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_driver_wext_data *drv = priv;
44c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	int timeout = 10; /* In case scan A and B bands it can be long */
45c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
46c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Not all drivers generate "scan completed" wireless event, so try to
47c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	 * read results after a timeout. */
48c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (drv->scan_complete_events) {
49c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/*
50c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	 * The driver seems to deliver SIOCGIWSCAN events to notify
51c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	 * when scan is complete, so use longer timeout to avoid race
52c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	 * conditions with scanning and following association request.
53c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	 */
54c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		timeout = 30;
55c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
56c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	wpa_printf(MSG_DEBUG, "Scan requested - scan timeout %d seconds",
57c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		   timeout);
58c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
59c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
60c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			       drv->ctx);
61c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
62c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
63c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt/**
64c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * wpa_driver_wext_combo_scan - Request the driver to initiate combo scan
65c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_wext_init()
66c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * @params: Scan parameters
67c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt * Returns: 0 on success, -1 on failure
68c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt */
69c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtint wpa_driver_wext_combo_scan(void *priv, struct wpa_driver_scan_params *params)
70c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
71c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	char buf[WEXT_CSCAN_BUF_LEN];
72c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_driver_wext_data *drv = priv;
73c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct iwreq iwr;
74c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	int ret, bp;
75c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	unsigned i;
76c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
77c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
78c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (!drv->driver_is_started) {
79c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: Driver stopped", __func__);
80c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return 0;
81c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
82c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
83c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: Start", __func__);
84c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
85c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set list of SSIDs */
86c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp = WEXT_CSCAN_HEADER_SIZE;
87c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
88c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	for(i=0; i < params->num_ssids; i++) {
89c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if ((bp + IW_ESSID_MAX_SIZE + 10) >= (int)sizeof(buf))
90c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			break;
91c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_DEBUG, "For Scan: %s", params->ssids[i].ssid);
92c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = WEXT_CSCAN_SSID_SECTION;
93c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = params->ssids[i].ssid_len;
94c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		os_memcpy(&buf[bp], params->ssids[i].ssid, params->ssids[i].ssid_len);
95c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		bp += params->ssids[i].ssid_len;
96c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
97c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
98c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set list of channels */
99c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
100c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = 0;
101c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
102c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set passive dwell time (default is 250) */
103c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
104c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME;
105c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME >> 8);
106c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
107c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set home dwell time (default is 40) */
108c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
109c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
110c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
111c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
112c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memset(&iwr, 0, sizeof(iwr));
113c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
114c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.pointer = buf;
115c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.length = bp;
116c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
117c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
118d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		if (!drv->bgscan_enabled)
119d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt			wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
120d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		else
121d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt			ret = 0;	/* Hide error in case of bg scan */
122c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
123c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	return ret;
124c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
125c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
126c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtstatic int wpa_driver_wext_set_cscan_params(char *buf, size_t buf_len, char *cmd)
127c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
128c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	char *pasv_ptr;
129c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	int bp, i;
130c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	u16 pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
131c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	u8 channel;
132c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
133c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s: %s", __func__, cmd);
134c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
135c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Get command parameters */
136c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	pasv_ptr = os_strstr(cmd, ",TIME=");
137c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (pasv_ptr) {
138c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		*pasv_ptr = '\0';
139c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		pasv_ptr += 6;
140c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		pasv_dwell = (u16)atoi(pasv_ptr);
141c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (pasv_dwell == 0)
142c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_DEF;
143c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
144c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	channel = (u8)atoi(cmd + 5);
145c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
146c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp = WEXT_CSCAN_HEADER_SIZE;
147c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
148c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
149c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set list of channels */
150c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
151c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = channel;
152c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (channel != 0) {
153c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		i = (pasv_dwell - 1) / WEXT_CSCAN_PASV_DWELL_TIME_DEF;
154c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		for (; i > 0; i--) {
155c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			if ((size_t)(bp + 12) >= buf_len)
156c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt				break;
157c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
158c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			buf[bp++] = channel;
159c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
160c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else {
161c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (pasv_dwell > WEXT_CSCAN_PASV_DWELL_TIME_MAX)
162c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			pasv_dwell = WEXT_CSCAN_PASV_DWELL_TIME_MAX;
163c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
164c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
165c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set passive dwell time (default is 250) */
166c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
167c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (channel != 0) {
168c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME_DEF;
169c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME_DEF >> 8);
170c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else {
171c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = (u8)pasv_dwell;
172c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		buf[bp++] = (u8)(pasv_dwell >> 8);
173c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
174c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
175c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set home dwell time (default is 40) */
176c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
177c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
178c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
179c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
180c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	/* Set cscan type */
181c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_TYPE_SECTION;
182c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_CSCAN_TYPE_PASSIVE;
183c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	return bp;
184c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
185c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
186c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtstatic char *wpa_driver_get_country_code(int channels)
187c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
188c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	char *country = "US"; /* WEXT_NUMBER_SCAN_CHANNELS_FCC */
189c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
190c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (channels == WEXT_NUMBER_SCAN_CHANNELS_ETSI)
191c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		country = "EU";
192c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	else if( channels == WEXT_NUMBER_SCAN_CHANNELS_MKK1)
193c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		country = "JP";
194c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	return country;
195c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
196c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
197c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtstatic int wpa_driver_set_backgroundscan_params(void *priv)
198c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
199c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_driver_wext_data *drv = priv;
200c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_supplicant *wpa_s;
201c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct iwreq iwr;
202c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	int ret = 0, i = 0, bp;
203c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	char buf[WEXT_PNO_MAX_COMMAND_SIZE];
204c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_ssid *ssid_conf;
205c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
206c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (drv == NULL) {
207c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__);
208c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return -1;
209c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
210c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (drv->ctx == NULL) {
211c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__);
212c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return -1;
213c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
214c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	wpa_s = (struct wpa_supplicant *)(drv->ctx);
215c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (wpa_s->conf == NULL) {
216c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__);
217c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return -1;
218c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
219c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	ssid_conf = wpa_s->conf->ssid;
220c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
221c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp = WEXT_PNOSETUP_HEADER_SIZE;
222c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
223d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	buf[bp++] = WEXT_PNO_TLV_PREFIX;
224c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_TLV_VERSION;
225c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
226c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_TLV_RESERVED;
227c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
228c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	while ((i < WEXT_PNO_AMOUNT) && (ssid_conf != NULL)) {
229c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		/* Check that there is enough space needed for 1 more SSID, the other sections and null termination */
230c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf))
231c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			break;
232c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= IW_ESSID_MAX_SIZE)){
233c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_printf(MSG_DEBUG, "For PNO Scan: %s", ssid_conf->ssid);
234c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			buf[bp++] = WEXT_PNO_SSID_SECTION;
235c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			buf[bp++] = ssid_conf->ssid_len;
236c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			os_memcpy(&buf[bp], ssid_conf->ssid, ssid_conf->ssid_len);
237c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			bp += ssid_conf->ssid_len;
238c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			i++;
239c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
240c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		ssid_conf = ssid_conf->next;
241c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
242c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
243c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
244c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", WEXT_PNO_SCAN_INTERVAL);
245c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
246c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
247c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_REPEAT_SECTION;
248c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", WEXT_PNO_REPEAT);
249c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp += WEXT_PNO_REPEAT_LENGTH;
250c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
251c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
252c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", WEXT_PNO_MAX_REPEAT);
253c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
254c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
255c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memset(&iwr, 0, sizeof(iwr));
256c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
257c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.pointer = buf;
258c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.length = bp;
259c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
260c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
261c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
262c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (ret < 0) {
263c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret);
264c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->errors++;
265c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (drv->errors > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
266c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			drv->errors = 0;
267c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
268c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
269c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else {
270c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->errors = 0;
271c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
272c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	return ret;
273c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
274c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
275c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
276c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidtint wpa_driver_wext_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len )
277c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt{
278c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_driver_wext_data *drv = priv;
279c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
280c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	struct iwreq iwr;
281c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	int ret = 0, flags;
282c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
283c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
284c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
285c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
286c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
287c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return -1;
288c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
289c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
290c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
291d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		os_strncpy(cmd, RSSI_CMD, MAX_DRV_CMD_SIZE);
292c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
293c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		int no_of_chan;
294c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
295c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		no_of_chan = atoi(cmd + 13);
296c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
297c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_driver_get_country_code(no_of_chan));
298c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else if (os_strcasecmp(cmd, "STOP") == 0) {
299f9694904d6ea5c37db1cd48ba0afa16f4bfc9f9aDmitry Shmidt		linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0);
300c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
301c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_DEBUG,"Reload command");
302c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
303c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		return ret;
304c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else if( os_strcasecmp(cmd, "BGSCAN-START") == 0 ) {
305c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		ret = wpa_driver_set_backgroundscan_params(priv);
306c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (ret < 0) {
307c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			return ret;
308c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
309c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		os_strncpy(cmd, "PNOFORCE 1", MAX_DRV_CMD_SIZE);
310c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->bgscan_enabled = 1;
311c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else if( os_strcasecmp(cmd, "BGSCAN-STOP") == 0 ) {
312c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		os_strncpy(cmd, "PNOFORCE 0", MAX_DRV_CMD_SIZE);
313c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->bgscan_enabled = 0;
314c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
315c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
316c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memset(&iwr, 0, sizeof(iwr));
317c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
318c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	os_memcpy(buf, cmd, strlen(cmd) + 1);
319c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.pointer = buf;
320c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	iwr.u.data.length = buf_len;
321c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
322c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if( os_strncasecmp(cmd, "CSCAN", 5) == 0 ) {
323c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (!wpa_s->scanning && ((wpa_s->wpa_state <= WPA_SCANNING) ||
324c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt					(wpa_s->wpa_state >= WPA_COMPLETED))) {
325c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			iwr.u.data.length = wpa_driver_wext_set_cscan_params(buf, buf_len, cmd);
326c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		} else {
327c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_printf(MSG_ERROR, "Ongoing Scan action...");
328c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			return ret;
329c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
330c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
331c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
332c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
333c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt
334c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	if (ret < 0) {
335c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, cmd);
336c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->errors++;
337c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		if (drv->errors > WEXT_NUMBER_SEQUENTIAL_ERRORS) {
338c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			drv->errors = 0;
339c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
340c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
341c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	} else {
342c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		drv->errors = 0;
343c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		ret = 0;
344d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		if ((os_strcasecmp(cmd, RSSI_CMD) == 0) ||
345d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		    (os_strcasecmp(cmd, LINKSPEED_CMD) == 0) ||
346c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		    (os_strcasecmp(cmd, "MACADDR") == 0) ||
347c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		    (os_strcasecmp(cmd, "GETPOWER") == 0) ||
348c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		    (os_strcasecmp(cmd, "GETBAND") == 0)) {
349c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			ret = strlen(buf);
350c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		} else if (os_strcasecmp(cmd, "START") == 0) {
351c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			drv->driver_is_started = TRUE;
352f9694904d6ea5c37db1cd48ba0afa16f4bfc9f9aDmitry Shmidt			linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
353c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			/* os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
354c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); */
355c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		} else if (os_strcasecmp(cmd, "STOP") == 0) {
356c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			drv->driver_is_started = FALSE;
357c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			/* wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); */
358c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		} else if (os_strncasecmp(cmd, "CSCAN", 5) == 0) {
359c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_driver_wext_set_scan_timeout(priv);
360c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt			wpa_supplicant_notify_scanning(wpa_s, 1);
361c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		}
362c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt		wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
363c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	}
364c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt	return ret;
365c208ac5eb62bad8f6346aaa98c69462dff0337feDmitry Shmidt}
366d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt
367d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidtint wpa_driver_signal_poll(void *priv, struct wpa_signal_info *si)
368d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt{
369d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	char buf[MAX_DRV_CMD_SIZE];
370d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	struct wpa_driver_wext_data *drv = priv;
371d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	char *prssi;
372d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	int res;
373d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt
374d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	os_memset(si, 0, sizeof(*si));
375d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	res = wpa_driver_wext_driver_cmd(priv, RSSI_CMD, buf, sizeof(buf));
376d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	/* Answer: SSID rssi -Val */
377d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	if (res < 0)
378d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		return res;
379d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	prssi = strcasestr(buf, RSSI_CMD);
380d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	if (!prssi)
381d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		return -1;
382d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	si->current_signal = atoi(prssi + strlen(RSSI_CMD) + 1);
383d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt
384d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	res = wpa_driver_wext_driver_cmd(priv, LINKSPEED_CMD, buf, sizeof(buf));
385d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	/* Answer: LinkSpeed Val */
386d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	if (res < 0)
387d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt		return res;
388d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	si->current_txrate = atoi(buf + strlen(LINKSPEED_CMD) + 1) * 1000;
389d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt
390d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt	return 0;
391d7edab78ddecd5492c22006c1b1e23c6c6b2a479Dmitry Shmidt}
392