]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Android: wext: Add sched_scan functions for PNO
authorDmitry Shmidt <dimitrysh@google.com>
Fri, 25 Nov 2011 19:49:03 +0000 (21:49 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 29 Nov 2011 13:18:45 +0000 (15:18 +0200)
(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)

src/drivers/android_drv.h
src/drivers/driver_wext.c
src/drivers/driver_wext.h

index 541711681a4d13e53f3346a1871949c6f6f99527..5906527a017e5a69648ca9050608b94c0da3abd1 100644 (file)
 
 #define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE "
 
+#define MAX_SSID_LEN 32
+
+#define MAX_DRV_CMD_SIZE               248
+#define DRV_NUMBER_SEQUENTIAL_ERRORS   4
+
+#define WEXT_PNOSETUP_HEADER           "PNOSETUP "
+#define WEXT_PNOSETUP_HEADER_SIZE      9
+#define WEXT_PNO_TLV_PREFIX            'S'
+#define WEXT_PNO_TLV_VERSION           '1'
+#define WEXT_PNO_TLV_SUBVERSION                '2'
+#define WEXT_PNO_TLV_RESERVED          '0'
+#define WEXT_PNO_VERSION_SIZE          4
+#define WEXT_PNO_AMOUNT                        16
+#define WEXT_PNO_SSID_SECTION          'S'
+/* SSID header size is SSID section type above + SSID length */
+#define WEXT_PNO_SSID_HEADER_SIZE      2
+#define WEXT_PNO_SCAN_INTERVAL_SECTION 'T'
+#define WEXT_PNO_SCAN_INTERVAL_LENGTH  2
+#define WEXT_PNO_SCAN_INTERVAL         30
+/* Scan interval size is scan interval section type + scan interval length
+ * above */
+#define WEXT_PNO_SCAN_INTERVAL_SIZE    (1 + WEXT_PNO_SCAN_INTERVAL_LENGTH)
+#define WEXT_PNO_REPEAT_SECTION                'R'
+#define WEXT_PNO_REPEAT_LENGTH         1
+#define WEXT_PNO_REPEAT                        4
+/* Repeat section size is Repeat section type + Repeat value length above */
+#define WEXT_PNO_REPEAT_SIZE           (1 + WEXT_PNO_REPEAT_LENGTH)
+#define WEXT_PNO_MAX_REPEAT_SECTION    'M'
+#define WEXT_PNO_MAX_REPEAT_LENGTH     1
+#define WEXT_PNO_MAX_REPEAT            3
+/* Max Repeat section size is Max Repeat section type + Max Repeat value length
+ * above */
+#define WEXT_PNO_MAX_REPEAT_SIZE       (1 + WEXT_PNO_MAX_REPEAT_LENGTH)
+/* This corresponds to the size of all sections expect SSIDs */
+#define WEXT_PNO_NONSSID_SECTIONS_SIZE \
+(WEXT_PNO_SCAN_INTERVAL_SIZE + WEXT_PNO_REPEAT_SIZE + WEXT_PNO_MAX_REPEAT_SIZE)
+/* PNO Max command size is total of header, version, ssid and other sections +
+ * Null termination */
+#define WEXT_PNO_MAX_COMMAND_SIZE \
+       (WEXT_PNOSETUP_HEADER_SIZE + WEXT_PNO_VERSION_SIZE \
+        + WEXT_PNO_AMOUNT * (WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN) \
+        + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1)
+
 #endif /* ANDROID_DRV_H */
index a4152b411fc95536eee87e8834a1ccf7fb164cfa..7389c3d2cdae0b73f396afe40167a6ea2d632e25 100644 (file)
@@ -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 */
 };
index 89c13eb758e82c03cbaa2da2c6294d5d7195a955..8bcbee6701697fabf5386b5c6a1d8cfcf510a904 100644 (file)
@@ -50,6 +50,12 @@ struct wpa_driver_wext_data {
        int cfg80211; /* whether driver is using cfg80211 */
 
        u8 max_level;
+
+#ifdef ANDROID
+       int errors;
+       int driver_is_started;
+       int bgscan_enabled;
+#endif /* ANDROID */
 };
 
 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);