OSDN Git Service

WEXT: Add combo scan support (DO NOT MERGE)
authorDmitry Shmidt <dimitrysh@google.com>
Mon, 16 Aug 2010 21:50:17 +0000 (14:50 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Mon, 16 Aug 2010 21:50:17 +0000 (14:50 -0700)
Change-Id: Ibedff7e8f75556ba8df7094b7cfa6de1d1eab2a8
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/scan.c
wpa_supplicant/src/drivers/driver.h
wpa_supplicant/src/drivers/driver_wext.c
wpa_supplicant/src/drivers/driver_wext.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 2d22e08..a5c256b 100644 (file)
@@ -1633,6 +1633,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        int ctrl_rsp = 0;
        int reply_len;
 
+       wpa_printf(MSG_ERROR, "CMD: %s", buf);
+
        if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
            os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
index 624e628..4b15d22 100644 (file)
@@ -92,6 +92,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
        enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
 #endif /* CONFIG_WPS */
 
+       wpa_printf(MSG_ERROR, "%s: scan_req = %d, ap_scan = %d", __func__,
+               wpa_s->scan_req, wpa_s->conf->ap_scan);
+
        if (wpa_s->disconnected && !wpa_s->scan_req) {
                wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
                return;
@@ -162,15 +165,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
                return;
        }
 
-       wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
-                  ssid ? "specific": "broadcast");
-       if (ssid) {
-               wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
-                                 ssid->ssid, ssid->ssid_len);
-               wpa_s->prev_scan_ssid = ssid;
-       } else
-               wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
-
 #ifdef CONFIG_WPS
        wps = wpas_wps_in_use(wpa_s->conf, &req_type);
 #endif /* CONFIG_WPS */
@@ -199,14 +193,22 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 
        wpa_supplicant_notify_scanning(wpa_s, 1);
 
+       wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
+                  ssid ? "specific": "broadcast");
+       if (ssid) {
+               wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
+                                 ssid->ssid, ssid->ssid_len);
+               wpa_s->prev_scan_ssid = ssid;
+       } else
+               wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
+
        if (wpa_s->use_client_mlme) {
                ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
                ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
                                             ssid ? ssid->ssid_len : 0);
        } else {
                wpa_drv_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
-               ret = wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL,
-                                  ssid ? ssid->ssid_len : 0);
+               ret = wpa_drv_scan(wpa_s, &ssid);
        }
 
        wpabuf_free(wps_ie);
index bb5f5b0..8c9db27 100644 (file)
@@ -369,6 +369,7 @@ struct ieee80211_rx_status {
         int ssi;
 };
 
+struct wpa_ssid;
 
 /**
  * struct wpa_driver_ops - Driver interface API definition
@@ -572,6 +573,23 @@ struct wpa_driver_ops {
        int (*scan)(void *priv, const u8 *ssid, size_t ssid_len);
 
        /**
+        * combo_scan - Request the driver to initiate combo scan
+        * @priv: private driver interface data
+        * @ssid_ptr: specific SSID to scan for (ProbeReq) or %NULL to scan for
+        *      all SSIDs (either active scan with broadcast SSID or passive
+        *      scan
+        * @ssid_conf: SSID list from configuration
+        *
+        * Returns: 0 on success, -1 on failure
+        *
+        * Once the scan results are ready, the driver should report scan
+        * results event for wpa_supplicant which will eventually request the
+        * results with wpa_driver_get_scan_results().
+        */
+       int (*combo_scan)(void *priv, struct wpa_ssid **ssid_prt,
+                          struct wpa_ssid *ssid_conf);
+
+       /**
         * get_scan_results - Fetch the latest scan results (old version)
         * @priv: private driver interface data
         * @results: pointer to buffer for scan results
index 2f0771d..1185af9 100644 (file)
@@ -142,7 +142,7 @@ int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
        os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 
        if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
-               perror("ioctl[SIOCGIWAP]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIWAP]");
                ret = -1;
        }
        os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
@@ -172,7 +172,7 @@ int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
                os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
 
        if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
-               perror("ioctl[SIOCSIWAP]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWAP]");
                ret = -1;
        }
 
@@ -198,7 +198,7 @@ int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
        iwr.u.essid.length = 32;
 
        if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
-               perror("ioctl[SIOCGIWESSID]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIWESSID]");
                ret = -1;
        } else {
                ret = iwr.u.essid.length;
@@ -256,7 +256,7 @@ int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
        iwr.u.essid.length = ssid_len;
 
        if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
-               perror("ioctl[SIOCSIWESSID]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWESSID]");
                ret = -1;
        }
 
@@ -282,7 +282,7 @@ int wpa_driver_wext_set_freq(void *priv, int freq)
        iwr.u.freq.e = 1;
 
        if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
-               perror("ioctl[SIOCSIWFREQ]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWFREQ]");
                ret = -1;
        }
 
@@ -363,6 +363,8 @@ wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
                wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
        } else if (os_strncmp(custom, "START", 5) == 0) {
                wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
+       } else if (os_strncmp(custom, "HANG", 4) == 0) {
+               wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
 #endif /* ANDROID */
        }
 }
@@ -806,7 +808,7 @@ try_again:
                        (struct sockaddr *) &from, &fromlen);
        if (left < 0) {
                if (errno != EINTR && errno != EAGAIN)
-                       perror("recvfrom(netlink)");
+                       wpa_printf(MSG_ERROR, "%s: recvfrom(netlink): %d", __func__, errno);
                return;
        }
 
@@ -865,7 +867,7 @@ static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv,
        os_memset(&ifr, 0, sizeof(ifr));
        os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
        if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
-               perror("ioctl[SIOCGIFFLAGS]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]");
                return -1;
        }
        *flags = ifr.ifr_flags & 0xffff;
@@ -894,7 +896,7 @@ static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv,
        os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
        ifr.ifr_flags = flags & 0xffff;
        if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
-               perror("SIOCSIFFLAGS");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]");
                return -1;
        }
        return 0;
@@ -934,14 +936,14 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
 
        drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
        if (drv->ioctl_sock < 0) {
-               perror("socket(PF_INET,SOCK_DGRAM)");
+               wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__);
                os_free(drv);
                return NULL;
        }
 
        s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        if (s < 0) {
-               perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+               wpa_printf(MSG_ERROR, "%s: socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)", __func__);
                close(drv->ioctl_sock);
                os_free(drv);
                return NULL;
@@ -951,7 +953,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
        local.nl_family = AF_NETLINK;
        local.nl_groups = RTMGRP_LINK;
        if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
-               perror("bind(netlink)");
+               wpa_printf(MSG_ERROR, "bind(netlink)");
                close(s);
                close(drv->ioctl_sock);
                os_free(drv);
@@ -964,7 +966,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
        drv->mlme_sock = -1;
 #ifdef ANDROID
        drv->errors = 0;
-       drv->driver_is_loaded = TRUE;
+       drv->driver_is_started = TRUE;
        drv->skip_disconnect = 0;
 #endif
        wpa_driver_wext_finish_drv_init(drv);
@@ -1074,7 +1076,6 @@ void wpa_driver_wext_deinit(void *priv)
        os_free(drv);
 }
 
-
 /**
  * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
  * @eloop_ctx: Unused
@@ -1089,6 +1090,34 @@ void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
        wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
 }
 
+/**
+ * wpa_driver_wext_set_scan_timeout - Set scan timeout to report scan completion
+ * @priv:  Pointer to private wext data from wpa_driver_wext_init()
+ *
+ * This function can be used to set registered timeout when starting a scan to
+ * generate a scan completed event if the driver does not report this.
+ */
+static void wpa_driver_wext_set_scan_timeout(void *priv)
+{
+       struct wpa_driver_wext_data *drv = priv;
+       int timeout = 10; /* In case scan A and B bands it can be long */
+
+       /* Not all drivers generate "scan completed" wireless event, so try to
+        * read results after a timeout. */
+       if (drv->scan_complete_events) {
+               /*
+                * The driver seems to deliver SIOCGIWSCAN events to notify
+                * when scan is complete, so use longer timeout to avoid race
+                * conditions with scanning and following association request.
+                */
+               timeout = 30;
+       }
+       wpa_printf(MSG_DEBUG, "Scan requested - scan timeout %d seconds",
+                  timeout);
+       eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
+       eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
+                              drv->ctx);
+}
 
 /**
  * wpa_driver_wext_scan - Request the driver to initiate scan
@@ -1103,7 +1132,7 @@ int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)
 {
        struct wpa_driver_wext_data *drv = priv;
        struct iwreq iwr;
-       int ret = 0, timeout;
+       int ret = 0;
        struct iw_scan_req req;
 #ifdef ANDROID
        struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
@@ -1140,28 +1169,104 @@ int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)
        }
 
        if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
-               perror("ioctl[SIOCSIWSCAN]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWSCAN]");
                ret = -1;
        }
 
-       /* Not all drivers generate "scan completed" wireless event, so try to
-        * read results after a timeout. */
-       timeout = 5;
-       if (drv->scan_complete_events) {
-               /*
-                * The driver seems to deliver SIOCGIWSCAN events to notify
-                * when scan is complete, so use longer timeout to avoid race
-                * conditions with scanning and following association request.
-                */
-               timeout = 30;
+       wpa_driver_wext_set_scan_timeout(priv);
+
+       return ret;
+}
+
+/**
+ * wpa_driver_wext_combo_scan - Request the driver to initiate combo scan
+ * @priv: Pointer to private wext data from wpa_driver_wext_init()
+ * @ssid_ptr: Pointer to current SSID from configuration list or %NULL to
+ *     scan for all SSIDs (either active scan with broadcast SSID or passive
+ *     scan)
+ * @ssid_conf: SSID list from the configuration
+ * Returns: 0 on success, -1 on failure
+ *     Also updates @ssid_ptr to next specific scan item
+ */
+int wpa_driver_wext_combo_scan(void *priv, struct wpa_ssid **ssid_ptr,
+                              struct wpa_ssid *ssid_conf)
+{
+       char buf[WEXT_CSCAN_BUF_LEN];
+       struct wpa_driver_wext_data *drv = priv;
+       struct iwreq iwr;
+       int ret = 0, timeout, i = 0, bp;
+       struct wpa_ssid *ssid, *ssid_orig;
+       u8 *ssid_nm = NULL;
+       size_t ssid_len = 0;
+
+       struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx);
+       int scan_probe_flag = 0;
+
+       if (!drv->driver_is_started) {
+               wpa_printf(MSG_DEBUG, "%s: Driver stopped", __func__);
+               return -1;
        }
-       wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
-                  "seconds", ret, timeout);
-       eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
-       eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
-                              drv->ctx);
+
+       wpa_printf(MSG_DEBUG, "%s: Start", __func__);
+
+       /* Set list of SSIDs */
+       ssid_orig = (*ssid_ptr);
+       ssid = (*ssid_ptr) ? (*ssid_ptr) : ssid_conf;
+       bp = WEXT_CSCAN_HEADER_SIZE;
+       os_memcpy(buf, WEXT_CSCAN_HEADER, bp);
+       while (i < WEXT_CSCAN_AMOUNT) {
+               if ((bp + IW_ESSID_MAX_SIZE + 10) >= (int)sizeof(buf))
+                       break;
+               *ssid_ptr = ssid;
+               if (ssid == NULL)
+                       break;
+               if (!ssid->disabled && ssid->scan_ssid) {
+                       wpa_printf(MSG_DEBUG, "For Scan: %s", ssid->ssid);
+                       buf[bp++] = WEXT_CSCAN_SSID_SECTION;
+                       buf[bp++] = ssid->ssid_len;
+                       os_memcpy(&buf[bp], ssid->ssid, ssid->ssid_len);
+                       bp += ssid->ssid_len;
+                       i++;
+               }
+               ssid = ssid->next;
+       }
+
+       /* Set list of channels */
+       buf[bp++] = WEXT_CSCAN_CHANNEL_SECTION;
+       buf[bp++] = 0;
+
+       /* Set passive dwell time (default is 250) */
+       buf[bp++] = WEXT_CSCAN_PASV_DWELL_SECTION;
+       buf[bp++] = (u8)WEXT_CSCAN_PASV_DWELL_TIME;
+       buf[bp++] = (u8)(WEXT_CSCAN_PASV_DWELL_TIME >> 8);
+
+       /* Set home dwell time (default is 40) */
+       buf[bp++] = WEXT_CSCAN_HOME_DWELL_SECTION;
+       buf[bp++] = (u8)WEXT_CSCAN_HOME_DWELL_TIME;
+       buf[bp++] = (u8)(WEXT_CSCAN_HOME_DWELL_TIME >> 8);
+
+       os_memset(&iwr, 0, sizeof(iwr));
+       os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+       iwr.u.data.pointer = buf;
+       iwr.u.data.length = bp;
+
+       if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (cscan): %d", ret);
+               *ssid_ptr = ssid_orig;
+               goto old_scan;
+       }
+
+       wpa_driver_wext_set_scan_timeout(priv);
 
        return ret;
+
+old_scan:
+       if (*ssid_ptr) {
+               ssid_nm = (*ssid_ptr)->ssid;
+               ssid_len = (*ssid_ptr)->ssid_len;
+       }
+
+       return wpa_driver_wext_scan(priv, ssid_nm, ssid_len);
 }
 
 
@@ -1195,7 +1300,7 @@ static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
                                   "trying larger buffer (%lu bytes)",
                                   (unsigned long) res_buf_len);
                } else {
-                       perror("ioctl[SIOCGIWSCAN]");
+                       wpa_printf(MSG_ERROR, "ioctl[SIOCGIWSCAN]: %d", errno);
                        os_free(res_buf);
                        return NULL;
                }
@@ -1633,7 +1738,7 @@ static int wpa_driver_wext_get_range(void *priv)
                sizeof(range->enc_capa);
 
        if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
-               perror("ioctl[SIOCGIWRANGE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIRANGE]");
                os_free(range);
                return -1;
        } else if (iwr.u.data.length >= minlen &&
@@ -1718,7 +1823,7 @@ static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv,
 
        ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr);
        if (ret < 0)
-               perror("ioctl[SIOCSIWENCODEEXT] PMK");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT] PMK");
        os_free(ext);
 
        return ret;
@@ -1811,7 +1916,7 @@ static int wpa_driver_wext_set_key_ext(void *priv, wpa_alg alg,
                        ret = -2;
                }
 
-               perror("ioctl[SIOCSIWENCODEEXT]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODEEXT]");
        }
 
        os_free(ext);
@@ -1885,7 +1990,7 @@ int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
        iwr.u.encoding.length = key_len;
 
        if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
-               perror("ioctl[SIOCSIWENCODE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]");
                ret = -1;
        }
 
@@ -1897,7 +2002,7 @@ int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
                iwr.u.encoding.pointer = (caddr_t) NULL;
                iwr.u.encoding.length = 0;
                if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
-                       perror("ioctl[SIOCSIWENCODE] (set_tx)");
+                       wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE] (set_tx)");
                        ret = -1;
                }
        }
@@ -1946,7 +2051,7 @@ static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
        iwr.u.data.length = sizeof(mlme);
 
        if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
-               perror("ioctl[SIOCSIWMLME]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMLME]");
                ret = -1;
        }
 
@@ -1971,7 +2076,7 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
        os_memset(&iwr, 0, sizeof(iwr));
        os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
        if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
-               perror("ioctl[SIOCGIWMODE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]");
                iwr.u.mode = IW_MODE_INFRA;
        }
 
@@ -2029,7 +2134,7 @@ static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie,
        iwr.u.data.length = ie_len;
 
        if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
-               perror("ioctl[SIOCSIWGENIE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWGENIE]");
                ret = -1;
        }
 
@@ -2106,7 +2211,7 @@ wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv,
        }
 
        if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
-               perror("ioctl[SIOCSIWENCODE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]");
                ret = -1;
        }
 
@@ -2268,7 +2373,7 @@ int wpa_driver_wext_set_mode(void *priv, int mode)
        }
 
        if (errno != EBUSY) {
-               perror("ioctl[SIOCSIWMODE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]");
                goto done;
        }
 
@@ -2277,7 +2382,7 @@ int wpa_driver_wext_set_mode(void *priv, int mode)
         * down, try to set the mode again, and bring it back up.
         */
        if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
-               perror("ioctl[SIOCGIWMODE]");
+               wpa_printf(MSG_ERROR, "ioctl[SIOCGIWMODE]");
                goto done;
        }
 
@@ -2292,7 +2397,7 @@ int wpa_driver_wext_set_mode(void *priv, int mode)
                /* Try to set the mode again while the interface is down */
                iwr.u.mode = new_mode;
                if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
-                       perror("ioctl[SIOCSIWMODE]");
+                       wpa_printf(MSG_ERROR, "ioctl[SIOCSIWMODE]");
                else
                        ret = 0;
 
@@ -2329,7 +2434,7 @@ static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv,
 
        if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
                if (errno != EOPNOTSUPP)
-                       perror("ioctl[SIOCSIWPMKSA]");
+                       wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPMKSA]");
                ret = -1;
        }
 
@@ -2428,29 +2533,26 @@ static int wpa_driver_priv_driver_cmd( void *priv, char *cmd, char *buf, size_t
 
        wpa_printf(MSG_DEBUG, "%s %s len = %d", __func__, cmd, buf_len);
 
-       if (!drv->driver_is_loaded && (os_strcasecmp(cmd, "START") != 0)) {
+       if (!drv->driver_is_started && (os_strcasecmp(cmd, "START") != 0)) {
                wpa_printf(MSG_ERROR,"WEXT: Driver not initialized yet");
                return -1;
        }
 
        if (os_strcasecmp(cmd, "RSSI-APPROX") == 0) {
                os_strncpy(cmd, "RSSI", MAX_DRV_CMD_SIZE);
-       }
-       else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
+       } else if( os_strncasecmp(cmd, "SCAN-CHANNELS", 13) == 0 ) {
                int no_of_chan;
 
                no_of_chan = atoi(cmd + 13);
                os_snprintf(cmd, MAX_DRV_CMD_SIZE, "COUNTRY %s",
                        wpa_driver_get_country_code(no_of_chan));
-       }
-       else if (os_strcasecmp(cmd, "STOP") == 0) {
+       } else if (os_strcasecmp(cmd, "STOP") == 0) {
                if ((wpa_driver_wext_get_ifflags(drv, &flags) == 0) &&
                    (flags & IFF_UP)) {
                        wpa_printf(MSG_ERROR, "WEXT: %s when iface is UP", cmd);
                        wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
                }
-       }
-       else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
+       } else if( os_strcasecmp(cmd, "RELOAD") == 0 ) {
                wpa_printf(MSG_DEBUG,"Reload command");
                wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
                return ret;
@@ -2462,9 +2564,7 @@ static int wpa_driver_priv_driver_cmd( void *priv, char *cmd, char *buf, size_t
        iwr.u.data.pointer = buf;
        iwr.u.data.length = buf_len;
 
-       if ((ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr)) < 0) {
-               perror("ioctl[SIOCSIWPRIV]");
-       }
+       ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
 
        if (ret < 0) {
                wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret, cmd);
@@ -2473,22 +2573,21 @@ static int wpa_driver_priv_driver_cmd( void *priv, char *cmd, char *buf, size_t
                        drv->errors = 0;
                        wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
                }
-       }
-       else {
+       } else {
                drv->errors = 0;
                ret = 0;
                if ((os_strcasecmp(cmd, "RSSI") == 0) ||
                    (os_strcasecmp(cmd, "LINKSPEED") == 0) ||
-                   (os_strcasecmp(cmd, "MACADDR") == 0)) {
+                   (os_strcasecmp(cmd, "MACADDR") == 0) ||
+                   (os_strcasecmp(cmd, "GETPOWER") == 0) ||
+                   (os_strcasecmp(cmd, "GETBAND") == 0)) {
                        ret = strlen(buf);
-               }
-               else if (os_strcasecmp(cmd, "START") == 0) {
-                       drv->driver_is_loaded = TRUE;
+               } else if (os_strcasecmp(cmd, "START") == 0) {
+                       drv->driver_is_started = TRUE;
                        /* os_sleep(0, WPA_DRIVER_WEXT_WAIT_US);
                        wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); */
-               }
-               else if (os_strcasecmp(cmd, "STOP") == 0) {
-                       drv->driver_is_loaded = FALSE;
+               } else if (os_strcasecmp(cmd, "STOP") == 0) {
+                       drv->driver_is_started = FALSE;
                        /* wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); */
                }
                wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf));
@@ -2508,6 +2607,7 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
        .set_countermeasures = wpa_driver_wext_set_countermeasures,
        .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
        .scan = wpa_driver_wext_scan,
+       .combo_scan = wpa_driver_wext_combo_scan,
        .get_scan_results2 = wpa_driver_wext_get_scan_results,
        .deauthenticate = wpa_driver_wext_deauthenticate,
        .disassociate = wpa_driver_wext_disassociate,
index f6b76a9..29ef44b 100644 (file)
@@ -45,7 +45,7 @@ struct wpa_driver_wext_data {
        int scan_complete_events;
 #ifdef ANDROID
        int errors;
-       int driver_is_loaded;
+       int driver_is_started;
        int skip_disconnect;
 #endif
 };
@@ -63,6 +63,8 @@ int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
                            int set_tx, const u8 *seq, size_t seq_len,
                            const u8 *key, size_t key_len);
 int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len);
+int wpa_driver_wext_combo_scan(void *priv, struct wpa_ssid **ssid_ptr,
+                              struct wpa_ssid *ssid_conf);
 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv);
 
 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -92,6 +94,23 @@ int wpa_driver_wext_keymgmt2wext(int keymgmt);
 #define WPA_DRIVER_WEXT_WAIT_US                400000
 #define MAX_DRV_CMD_SIZE               248
 #define WEXT_NUMBER_SEQUENTIAL_ERRORS  4
+#define WEXT_CSCAN_AMOUNT              9
+#define WEXT_CSCAN_BUF_LEN             360
+#define WEXT_CSCAN_HEADER              "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE         12
+#define WEXT_CSCAN_SSID_SECTION                'S'
+#define WEXT_CSCAN_CHANNEL_SECTION     'C'
+#define WEXT_CSCAN_NPROBE_SECTION      'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION  'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION  'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION  'H'
+#define WEXT_CSCAN_TYPE_SECTION                'T'
+#define WEXT_CSCAN_TYPE_DEFAULT                0
+#define WEXT_CSCAN_TYPE_PASSIVE                1
+#define WEXT_CSCAN_PASV_DWELL_TIME     130
+#define WEXT_CSCAN_PASV_DWELL_TIME_DEF 250
+#define WEXT_CSCAN_PASV_DWELL_TIME_MAX 3000
+#define WEXT_CSCAN_HOME_DWELL_TIME     130
 #endif
 
 #endif /* DRIVER_WEXT_H */
index b66061e..beec16e 100644 (file)
@@ -1484,6 +1484,30 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
        return NULL;
 }
 
+int wpa_drv_scan(struct wpa_supplicant *wpa_s, struct wpa_ssid **ssid_ptr)
+{
+       u8 *ssid_nm = NULL;
+       size_t ssid_len = 0;
+       int ret = -1;
+
+       if (wpa_s->driver->combo_scan) {
+               ret = wpa_s->driver->combo_scan(wpa_s->drv_priv, ssid_ptr,
+                                               wpa_s->conf->ssid);
+               if (!ret) {
+                       wpa_s->prev_scan_ssid = (*ssid_ptr) ?
+                                       (*ssid_ptr) : BROADCAST_SSID_SCAN;
+               }
+       }
+       else if (wpa_s->driver->scan) {
+               if (*ssid_ptr) {
+                       ssid_nm = (*ssid_ptr)->ssid;
+                       ssid_len = (*ssid_ptr)->ssid_len;
+               }
+
+               ret = wpa_s->driver->scan(wpa_s->drv_priv, ssid_nm, ssid_len);
+       }
+       return ret;
+}
 
 static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
                                     const char *name)
index 188d9a6..0771077 100644 (file)
@@ -421,6 +421,7 @@ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec);
 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
                                    int scanning);
+int wpa_drv_scan(struct wpa_supplicant *wpa_s, struct wpa_ssid **ssid_prt);
 
 /* events.c */
 void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);
@@ -507,15 +508,6 @@ static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s,
        return -1;
 }
 
-static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s, const u8 *ssid,
-                              size_t ssid_len)
-{
-       if (wpa_s->driver->scan) {
-               return wpa_s->driver->scan(wpa_s->drv_priv, ssid, ssid_len);
-       }
-       return -1;
-}
-
 static inline int wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s,
                                           struct wpa_scan_result *results,
                                           size_t max_size)