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 132748d5ff9a4f58551a99e72432252fee3bf1f369Dmitry Shmidt#include "hardware_legacy/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 209002fdbdf86753148dafcf910ad47fa0a1b85471Dmitry Shmidt#define MAX_WPSP2PIE_CMD_SIZE 512 21776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt 22d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidttypedef struct android_wifi_priv_cmd { 23d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt char *buf; 24d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int used_len; 25d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int total_len; 26d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt} android_wifi_priv_cmd; 27d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 28991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic int drv_errors = 0; 29991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 30991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) 31991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt{ 32991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors++; 33991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 34991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 35991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 36991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 37991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt} 38991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 39b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtint wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, 40b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt size_t buf_len ) 41b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 42b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 43b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 44d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt struct ifreq ifr; 45d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt android_wifi_priv_cmd priv_cmd; 46b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = 0; 47b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 48b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (os_strcasecmp(cmd, "STOP") == 0) { 49776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0); 50b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); 51b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "START") == 0) { 52776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1); 53b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); 54b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "MACADDR") == 0) { 55b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt u8 macaddr[ETH_ALEN] = {}; 56b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 57776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr); 58b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!ret) 59b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = os_snprintf(buf, buf_len, 60b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); 61d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } else { /* Use private command */ 62b7a3187fbbba0991b789298cb208d913334a6acbDmitry Shmidt os_memcpy(buf, cmd, strlen(cmd) + 1); 63d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 64d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&priv_cmd, 0, sizeof(priv_cmd)); 6530277c38a4fb41c7f71c790cd637f0d0aea94cc3Dmitry Shmidt os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 66d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 67d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.buf = buf; 68d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.used_len = buf_len; 69d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.total_len = buf_len; 70d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ifr.ifr_data = &priv_cmd; 71d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 72776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) { 73d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__); 74991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 75991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 76991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 77d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = 0; 78d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt if ((os_strcasecmp(cmd, "LINKSPEED") == 0) || 790428c19916e443cb002cba53263c3421ca6bd2d3Dmitry Shmidt (os_strcasecmp(cmd, "RSSI") == 0) || 80ef8e2e571ffc2141a05c0087523e674b92ac2ea8Dmitry Shmidt (os_strcasecmp(cmd, "GETBAND") == 0) || 81ef8e2e571ffc2141a05c0087523e674b92ac2ea8Dmitry Shmidt (os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0)) 82d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = strlen(buf); 836d97ec46bbec3f31c652c0208e3393d7aa2bee71Dmitry Shmidt else if ((os_strncasecmp(cmd, "COUNTRY", 7) == 0) || 846d97ec46bbec3f31c652c0208e3393d7aa2bee71Dmitry Shmidt (os_strncasecmp(cmd, "SETBAND", 7) == 0)) 85f65a4f72f06979609a89ad9a494a5aa9f0744980Dmitry Shmidt wpa_supplicant_event(drv->ctx, 86f65a4f72f06979609a89ad9a494a5aa9f0744980Dmitry Shmidt EVENT_CHANNEL_LIST_CHANGED, NULL); 87d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf)); 88d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } 89b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } 90b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 91b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 92b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 93b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) 94b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 95b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 96b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 97b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 98b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 99b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration); 100b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1); 101b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 102b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 103fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidtint wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) 104fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt{ 105776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt /* Return 0 till we handle p2p_presence request completely in the driver */ 106776e94c9c91c7cbbd0bf3ba12ad77ae1ad29f8f9Dmitry Shmidt return 0; 107fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt} 108fd38f980c1e877dbc7da6204cc9208e3dbbf0546Dmitry Shmidt 109b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) 110b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 111b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 112b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 113b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 114b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 115b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow); 116b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf) + 1); 117b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 118b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 119b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, 120b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *proberesp, 121b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *assocresp) 122b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 123b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_WPSP2PIE_CMD_SIZE]; 124b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct wpabuf *ap_wps_p2p_ie = NULL; 125b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *_cmd = "SET_AP_WPS_P2P_IE"; 126b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *pbuf; 127b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int ret = 0; 128b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int i; 129b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct cmd_desc { 130b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int cmd; 131b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *src; 132b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } cmd_arr[] = { 133b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x1, beacon}, 134b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x2, proberesp}, 135b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x4, assocresp}, 136b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {-1, NULL} 137b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt }; 138b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 139b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 140b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt for (i = 0; cmd_arr[i].cmd != -1; i++) { 141b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memset(buf, 0, sizeof(buf)); 142b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf = buf; 143b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd); 144b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt *pbuf++ = '\0'; 145b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ap_wps_p2p_ie = cmd_arr[i].src ? 146b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_dup(cmd_arr[i].src) : NULL; 147b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ap_wps_p2p_ie) { 148b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie)); 149b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, 150b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); 151b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_free(ap_wps_p2p_ie); 152b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ret < 0) 153b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt break; 154b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 155b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 156b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 157b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return ret; 158b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 159