aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/driver_wext.c
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2011-11-25 19:49:03 (GMT)
committerJouni Malinen <j@w1.fi>2011-11-29 13:18:45 (GMT)
commit5eb429101abdccbdb4a1dc545a68b54c6db1b53f (patch)
treea0af5f41e1d9945d7130bb2cdb276e7fcaed256c /src/drivers/driver_wext.c
parent06e356fe14eb639ed41371dbe6a867bf89dcbed1 (diff)
downloadhostap-5eb429101abdccbdb4a1dc545a68b54c6db1b53f.zip
hostap-5eb429101abdccbdb4a1dc545a68b54c6db1b53f.tar.gz
hostap-5eb429101abdccbdb4a1dc545a68b54c6db1b53f.tar.bz2
Android: wext: Add sched_scan functions for PNO
(jm: This is based on the Android change that used driver_cmd. The same implementation is used for the actual driver interface, but the commands are now accessed through sched_scan/stop_sched_scan driver_ops instead of driver_cmd)
Diffstat (limited to 'src/drivers/driver_wext.c')
-rw-r--r--src/drivers/driver_wext.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index a4152b4..7389c3d 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -831,6 +831,12 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
drv->mlme_sock = -1;
+#ifdef ANDROID
+ drv->errors = 0;
+ drv->driver_is_started = TRUE;
+ drv->bgscan_enabled = 0;
+#endif /* ANDROID */
+
if (wpa_driver_wext_finish_drv_init(drv) < 0)
goto err3;
@@ -2316,6 +2322,129 @@ static const char * wext_get_radio_name(void *priv)
}
+#ifdef ANDROID
+
+static int android_wext_cmd(struct wpa_driver_wext_data *drv, const char *cmd)
+{
+ struct iwreq iwr;
+ char buf[MAX_DRV_CMD_SIZE];
+ int ret;
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+
+ os_memset(buf, 0, sizeof(buf));
+ os_strlcpy(buf, cmd, sizeof(buf));
+
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = sizeof(buf);
+
+ ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret,
+ cmd);
+ drv->errors++;
+ if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE
+ "HANGED");
+ }
+ return ret;
+ }
+
+ drv->errors = 0;
+ return 0;
+}
+
+
+static int wext_sched_scan(void *priv, struct wpa_driver_scan_params *params,
+ u32 interval)
+{
+ struct wpa_driver_wext_data *drv = priv;
+ struct iwreq iwr;
+ int ret = 0, i = 0, bp;
+ char buf[WEXT_PNO_MAX_COMMAND_SIZE];
+
+ bp = WEXT_PNOSETUP_HEADER_SIZE;
+ os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
+ buf[bp++] = WEXT_PNO_TLV_PREFIX;
+ buf[bp++] = WEXT_PNO_TLV_VERSION;
+ buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
+ buf[bp++] = WEXT_PNO_TLV_RESERVED;
+
+ while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
+ /*
+ * Check that there is enough space needed for 1 more SSID, the
+ * other sections and null termination.
+ */
+ if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE +
+ WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
+ break;
+
+ wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
+ params->ssids[i].ssid,
+ params->ssids[i].ssid_len);
+ buf[bp++] = WEXT_PNO_SSID_SECTION;
+ buf[bp++] = params->ssids[i].ssid_len;
+ os_memcpy(&buf[bp], params->ssids[i].ssid,
+ params->ssids[i].ssid_len);
+ bp += params->ssids[i].ssid_len;
+ i++;
+ }
+
+ buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
+ /* TODO: consider using interval parameter (interval in msec) instead
+ * of hardcoded value here */
+ os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
+ WEXT_PNO_SCAN_INTERVAL);
+ bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
+
+ buf[bp++] = WEXT_PNO_REPEAT_SECTION;
+ os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
+ WEXT_PNO_REPEAT);
+ bp += WEXT_PNO_REPEAT_LENGTH;
+
+ buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
+ os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
+ WEXT_PNO_MAX_REPEAT);
+ bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
+
+ os_memset(&iwr, 0, sizeof(iwr));
+ os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ iwr.u.data.pointer = buf;
+ iwr.u.data.length = bp;
+
+ ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
+ ret);
+ drv->errors++;
+ if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+ drv->errors = 0;
+ wpa_msg(drv->ctx, MSG_INFO,
+ WPA_EVENT_DRIVER_STATE "HANGED");
+ }
+ return ret;
+ }
+
+ drv->errors = 0;
+ drv->bgscan_enabled = 1;
+
+ return android_wext_cmd(drv, "PNOFORCE 1");
+}
+
+
+static int wext_stop_sched_scan(void *priv)
+{
+ struct wpa_driver_wext_data *drv = priv;
+ drv->bgscan_enabled = 0;
+ return android_wext_cmd(drv, "PNOFORCE 0");
+}
+
+#endif /* ANDROID */
+
+
const struct wpa_driver_ops wpa_driver_wext_ops = {
.name = "wext",
.desc = "Linux wireless extensions (generic)",
@@ -2336,4 +2465,8 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
.get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate,
.get_radio_name = wext_get_radio_name,
+#ifdef ANDROID
+ .sched_scan = wext_sched_scan,
+ .stop_sched_scan = wext_stop_sched_scan,
+#endif /* ANDROID */
};