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)
This commit is contained in:
parent
06e356fe14
commit
5eb429101a
3 changed files with 182 additions and 0 deletions
|
@ -14,4 +14,47 @@
|
|||
|
||||
#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 */
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue