driver_cmd_nl80211.c revision f65a4f72f06979609a89ad9a494a5aa9f0744980
1b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt/* 2b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * Driver interaction with extended Linux CFG8021 3b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 4b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 5b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 6b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * published by the Free Software Foundation. 7b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 8b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 9b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * license. 10b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 11b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt */ 12b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 13b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#include "driver_nl80211.h" 14991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#include "wpa_supplicant_i.h" 15991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#include "config.h" 16776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt#ifdef ANDROID 17776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt#include "android_drv.h" 18776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt#endif 19b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 20b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#define WPA_PS_ENABLED 0 21b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#define WPA_PS_DISABLED 1 22b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 239002fdbdf86753148dafcf910ad47fa0a1b85471Dmitry Shmidt#define MAX_WPSP2PIE_CMD_SIZE 512 24776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt 25d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidttypedef struct android_wifi_priv_cmd { 26d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt char *buf; 27d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int used_len; 28d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int total_len; 29d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt} android_wifi_priv_cmd; 30d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 31b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtint send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, 32b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 33b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt void *valid_data); 34b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 35991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic int drv_errors = 0; 36991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 37991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) 38991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt{ 39991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors++; 40991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 41991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 42991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 43991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 44991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt} 45991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 46b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int wpa_driver_set_power_save(void *priv, int state) 47b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 48b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 49b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nl_msg *msg; 51b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = -1; 52b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt enum nl80211_ps_state ps_state; 53b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 54b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = nlmsg_alloc(); 55b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!msg) 56b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return -1; 57b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 58776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 0, 0, 59b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NL80211_CMD_SET_POWER_SAVE, 0); 60b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 61b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (state == WPA_PS_ENABLED) 62b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ps_state = NL80211_PS_ENABLED; 63b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt else 64b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ps_state = NL80211_PS_DISABLED; 65b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 66b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 67b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); 68b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 69b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 70b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = NULL; 71b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (ret < 0) 72b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Set power mode fail: %d", ret); 73b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtnla_put_failure: 74b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nlmsg_free(msg); 75b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 76b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 77b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 78b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int get_power_mode_handler(struct nl_msg *msg, void *arg) 79b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 80b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 81b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 82b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int *state = (int *)arg; 83b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 84b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 85b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 86b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 87b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!tb[NL80211_ATTR_PS_STATE]) 88b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return NL_SKIP; 89b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 90b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (state) { 91b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt *state = (int)nla_get_u32(tb[NL80211_ATTR_PS_STATE]); 92b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Get power mode = %d", *state); 93b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt *state = (*state == NL80211_PS_ENABLED) ? 94b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt WPA_PS_ENABLED : WPA_PS_DISABLED; 95b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } 96b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 97b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return NL_SKIP; 98b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 99b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 100b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int wpa_driver_get_power_save(void *priv, int *state) 101b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 102b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 103b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 104b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nl_msg *msg; 105b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = -1; 106b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt enum nl80211_ps_state ps_state; 107b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 108b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = nlmsg_alloc(); 109b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!msg) 110b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return -1; 111b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 112776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 0, 0, 113b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NL80211_CMD_GET_POWER_SAVE, 0); 114b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 115b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 116b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 117b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, get_power_mode_handler, state); 118b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = NULL; 119b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (ret < 0) 120b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Get power mode fail: %d", ret); 121b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtnla_put_failure: 122b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nlmsg_free(msg); 123b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 124b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 125b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 126991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic int wpa_driver_set_backgroundscan_params(void *priv) 127991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt{ 128991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct i802_bss *bss = priv; 129991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 130991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_supplicant *wpa_s; 131991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct ifreq ifr; 132991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt android_wifi_priv_cmd priv_cmd; 133991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt int ret = 0, i = 0, bp; 134991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt char buf[WEXT_PNO_MAX_COMMAND_SIZE]; 135991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_ssid *ssid_conf; 136991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 137991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv == NULL) { 138991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__); 139991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 140991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 141991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv->ctx == NULL) { 142991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__); 143991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 144991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 145991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_s = (struct wpa_supplicant *)(drv->ctx); 146991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (wpa_s->conf == NULL) { 147991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__); 148991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 149991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 150991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ssid_conf = wpa_s->conf->ssid; 151991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 152991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp = WEXT_PNOSETUP_HEADER_SIZE; 153991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); 154991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_PREFIX; 155991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_VERSION; 156991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_SUBVERSION; 157991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_RESERVED; 158991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 159991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt while ((i < WEXT_PNO_AMOUNT) && (ssid_conf != NULL)) { 160991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt /* Check that there is enough space needed for 1 more SSID, the other sections and null termination */ 161991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf)) 162991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt break; 163991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= MAX_SSID_LEN)){ 164991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_DEBUG, "For PNO Scan: %s", ssid_conf->ssid); 165991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_SSID_SECTION; 166991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = ssid_conf->ssid_len; 167991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(&buf[bp], ssid_conf->ssid, ssid_conf->ssid_len); 168991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += ssid_conf->ssid_len; 169991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt i++; 170991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 171991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ssid_conf = ssid_conf->next; 172991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 173991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 174991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; 175991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", WEXT_PNO_SCAN_INTERVAL); 176991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; 177991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 178991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_REPEAT_SECTION; 179991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", WEXT_PNO_REPEAT); 180991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_REPEAT_LENGTH; 181991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 182991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; 183991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", WEXT_PNO_MAX_REPEAT); 184991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; 185991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 186991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 187991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt memset(&priv_cmd, 0, sizeof(priv_cmd)); 188991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 189991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 190991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.buf = buf; 191991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.used_len = bp; 192991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.total_len = bp; 193991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ifr.ifr_data = &priv_cmd; 194991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 195776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); 196991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 197991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) { 198991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret); 199991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 200991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 201991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 202991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 203991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return ret; 204991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt} 205991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 206b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtint wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, 207b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt size_t buf_len ) 208b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 209b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 210b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 211d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt struct ifreq ifr; 212d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt android_wifi_priv_cmd priv_cmd; 213b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = 0; 214b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 215b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (os_strcasecmp(cmd, "STOP") == 0) { 216776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); 217b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); 218b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "START") == 0) { 219776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1); 220b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); 221b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "MACADDR") == 0) { 222b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt u8 macaddr[ETH_ALEN] = {}; 223b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 224776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr); 225b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!ret) 226b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = os_snprintf(buf, buf_len, 227b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); 228b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "RELOAD") == 0) { 229b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 230b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) { 231b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int state; 232b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 233b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt state = atoi(cmd + 10); 234b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = wpa_driver_set_power_save(priv, state); 235991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) 236991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 237991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt else 238991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 239b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strncasecmp(cmd, "GETPOWER", 8) == 0) { 240b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int state = -1; 241b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 242b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = wpa_driver_get_power_save(priv, &state); 243991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (!ret && (state != -1)) { 244b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = os_snprintf(buf, buf_len, "POWERMODE = %d\n", state); 245991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 246991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 247991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 248991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 249d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } else { /* Use private command */ 250991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (os_strcasecmp(cmd, "BGSCAN-START") == 0) { 251991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ret = wpa_driver_set_backgroundscan_params(priv); 252991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) { 253991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return ret; 254991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 255991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, "PNOFORCE 1", 11); 256991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else if (os_strcasecmp(cmd, "BGSCAN-STOP") == 0) { 257991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, "PNOFORCE 0", 11); 258991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 259991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, cmd, strlen(cmd) + 1); 260991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 261d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 262d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&priv_cmd, 0, sizeof(priv_cmd)); 26330277c38a4fb41c7f71c790cd637f0d0aea94cc3Dmitry Shmidt os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 264d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 265d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.buf = buf; 266d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.used_len = buf_len; 267d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.total_len = buf_len; 268d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ifr.ifr_data = &priv_cmd; 269d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 270776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) { 271d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__); 272991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 273991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 274991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 275d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = 0; 276d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt if ((os_strcasecmp(cmd, "LINKSPEED") == 0) || 2770428c19916e443cb002cba53263c3421ca6bd2d3Dmitry Shmidt (os_strcasecmp(cmd, "RSSI") == 0) || 278776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt (os_strcasecmp(cmd, "GETBAND") == 0) ) 279d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = strlen(buf); 280f65a4f72f06979609a89ad9a494a5aa9f0744980Dmitry Shmidt else if (os_strcasecmp(cmd, "COUNTRY") == 0) 281f65a4f72f06979609a89ad9a494a5aa9f0744980Dmitry Shmidt wpa_supplicant_event(drv->ctx, 282f65a4f72f06979609a89ad9a494a5aa9f0744980Dmitry Shmidt EVENT_CHANNEL_LIST_CHANGED, NULL); 283d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf)); 284d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } 285b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } 286b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 287b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 288b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 289b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) 290b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 291b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 292b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 293b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 294b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 295b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration); 296b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1); 297b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 298b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 299fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidtint wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) 300fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt{ 301776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt /* Return 0 till we handle p2p_presence request completely in the driver */ 302776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt return 0; 303fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt} 304fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt 305b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) 306b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 307b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 308b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 309b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 310b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 311b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow); 312b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf) + 1); 313b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 314b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 315b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, 316b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *proberesp, 317b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *assocresp) 318b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 319b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_WPSP2PIE_CMD_SIZE]; 320b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct wpabuf *ap_wps_p2p_ie = NULL; 321b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *_cmd = "SET_AP_WPS_P2P_IE"; 322b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *pbuf; 323b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int ret = 0; 324b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int i; 325b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct cmd_desc { 326b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int cmd; 327b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *src; 328b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } cmd_arr[] = { 329b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x1, beacon}, 330b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x2, proberesp}, 331b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x4, assocresp}, 332b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {-1, NULL} 333b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt }; 334b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 335b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 336b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt for (i = 0; cmd_arr[i].cmd != -1; i++) { 337b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memset(buf, 0, sizeof(buf)); 338b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf = buf; 339b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd); 340b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt *pbuf++ = '\0'; 341b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ap_wps_p2p_ie = cmd_arr[i].src ? 342b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_dup(cmd_arr[i].src) : NULL; 343b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ap_wps_p2p_ie) { 344b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie)); 345b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, 346b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); 347b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_free(ap_wps_p2p_ie); 348b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ret < 0) 349b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt break; 350b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 351b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 352b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 353b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return ret; 354b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 355