Android: nl80211: Add Android specific PNO configuration
This is based on the Android driver_cmd changes that are converted to use the sched_scan/stop_sched_scan driver_ops for the case where the driver does not support the new nl80211 commands. Change-Id: Iaedc340f84650af422bd2ea57d2a8b0a9d4a5330 Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
parent
5eb429101a
commit
216eede830
1 changed files with 150 additions and 0 deletions
|
@ -43,6 +43,9 @@
|
|||
#include "rfkill.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "android_drv.h"
|
||||
#endif /* ANDROID */
|
||||
#ifdef CONFIG_LIBNL20
|
||||
/* libnl 2.0 compatibility code */
|
||||
#define nl_handle nl_sock
|
||||
|
@ -253,6 +256,11 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
|
|||
const u8 *buf, size_t buf_len, u64 *cookie,
|
||||
int no_cck, int no_ack, int offchanok);
|
||||
static int wpa_driver_nl80211_probe_req_report(void *priv, int report);
|
||||
#ifdef ANDROID
|
||||
static int android_pno_start(struct i802_bss *bss,
|
||||
struct wpa_driver_scan_params *params);
|
||||
static int android_pno_stop(struct i802_bss *bss);
|
||||
#endif /* ANDROID */
|
||||
|
||||
#ifdef HOSTAPD
|
||||
static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
|
||||
|
@ -2777,6 +2785,11 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
|
|||
struct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;
|
||||
size_t i;
|
||||
|
||||
#ifdef ANDROID
|
||||
if (!drv->capa.sched_scan_supported)
|
||||
return android_pno_start(bss, params);
|
||||
#endif /* ANDROID */
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
ssids = nlmsg_alloc();
|
||||
freqs = nlmsg_alloc();
|
||||
|
@ -2884,6 +2897,11 @@ static int wpa_driver_nl80211_stop_sched_scan(void *priv)
|
|||
int ret = 0;
|
||||
struct nl_msg *msg;
|
||||
|
||||
#ifdef ANDROID
|
||||
if (!drv->capa.sched_scan_supported)
|
||||
return android_pno_stop(bss);
|
||||
#endif /* ANDROID */
|
||||
|
||||
msg = nlmsg_alloc();
|
||||
if (!msg)
|
||||
return -1;
|
||||
|
@ -7694,6 +7712,138 @@ nla_put_failure:
|
|||
#endif /* CONFIG TDLS */
|
||||
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
typedef struct android_wifi_priv_cmd {
|
||||
char *buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
|
||||
static int drv_errors = 0;
|
||||
|
||||
static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
|
||||
{
|
||||
drv_errors++;
|
||||
if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
|
||||
drv_errors = 0;
|
||||
wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct ifreq ifr;
|
||||
android_wifi_priv_cmd priv_cmd;
|
||||
char buf[MAX_DRV_CMD_SIZE];
|
||||
int ret;
|
||||
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_memset(&priv_cmd, 0, sizeof(priv_cmd));
|
||||
os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
|
||||
|
||||
os_memset(buf, 0, sizeof(buf));
|
||||
os_strlcpy(buf, cmd, sizeof(buf));
|
||||
|
||||
priv_cmd.buf = buf;
|
||||
priv_cmd.used_len = sizeof(buf);
|
||||
priv_cmd.total_len = sizeof(buf);
|
||||
ifr.ifr_data = &priv_cmd;
|
||||
|
||||
ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
|
||||
__func__);
|
||||
wpa_driver_send_hang_msg(drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_errors = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int android_pno_start(struct i802_bss *bss,
|
||||
struct wpa_driver_scan_params *params)
|
||||
{
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct ifreq ifr;
|
||||
android_wifi_priv_cmd priv_cmd;
|
||||
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 + MAX_SSID_LEN +
|
||||
WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
|
||||
break;
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
|
||||
ssid[i].ssid, ssid[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;
|
||||
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;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
memset(&priv_cmd, 0, sizeof(priv_cmd));
|
||||
os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
|
||||
|
||||
priv_cmd.buf = buf;
|
||||
priv_cmd.used_len = bp;
|
||||
priv_cmd.total_len = bp;
|
||||
ifr.ifr_data = &priv_cmd;
|
||||
|
||||
ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
|
||||
ret);
|
||||
wpa_driver_send_hang_msg(drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_errors = 0;
|
||||
|
||||
return android_priv_cmd(bss, "PNOFORCE 1");
|
||||
}
|
||||
|
||||
|
||||
static int android_pno_stop(struct i802_bss *bss)
|
||||
{
|
||||
return android_priv_cmd(bss, "PNOFORCE 0");
|
||||
}
|
||||
|
||||
#endif /* ANDROID */
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||
.name = "nl80211",
|
||||
.desc = "Linux nl80211/cfg80211",
|
||||
|
|
Loading…
Reference in a new issue