net: wireless: WFD specific changes
Jun (Gab-Joo) Lim [Tue, 26 Jun 2012 03:29:57 +0000 (08:29 +0530)]
WFD specific changes integrated from broadcom patch

Bug 1001418
Bug 997838

Change-Id: I0632307bf5fb959def4ee12687430a14ab9e068e
Signed-off-by: Narayan Reddy <narayanr@nvidia.com>
Reviewed-on: http://git-master/r/111032
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-by: Rakesh Kumar <krakesh@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.h

index 2dc329b..f728c14 100644 (file)
@@ -3355,6 +3355,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        wl_af_params_t *af_params;
        wifi_p2p_ie_t *p2p_ie;
        wpa_ie_fixed_t *wps_ie;
+       wifi_wfd_ie_t *wfd_ie;
        scb_val_t scb_val;
        const struct ieee80211_mgmt *mgmt;
        struct wl_priv *wl = wiphy_priv(wiphy);
@@ -3363,6 +3364,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
        s32 bssidx = 0;
        u32 p2pie_len = 0;
        u32 wpsie_len = 0;
+       u32 wfdie_len = 0;
        u32 id;
        u32 retry = 0;
        bool ack = false;
@@ -3412,6 +3414,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                /* Total length of P2P Information Element */
                                p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
                        }
+                       if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len))
+                               != NULL) {
+                               /* Total length of WFD Information Element */
+                               wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+                       }
                        if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
                                != NULL) {
                                /* Order of Vendor IE is 1) WPS IE +
@@ -3423,7 +3430,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                                        sizeof(wps_ie->tag);
                                wl_cfgp2p_set_management_ie(wl, dev, bssidx,
                                        VNDR_IE_PRBRSP_FLAG,
-                                       (u8 *)wps_ie, wpsie_len + p2pie_len);
+                                       (u8 *)wps_ie, wpsie_len + p2pie_len + wfdie_len);
                        }
                        cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
                        goto exit;
@@ -3908,11 +3915,13 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
        wpa_ie_fixed_t *wpa_ie;
        bcm_tlv_t *wpa2_ie;
        wifi_p2p_ie_t *p2p_ie;
+       wifi_wfd_ie_t *wfd_ie;
        bool is_bssup = false;
        bool update_bss = false;
        bool pbc = false;
        u16 wpsie_len = 0;
        u16 p2pie_len = 0;
+       u32 wfdie_len = 0;
        u8 beacon_ie[IE_MAX_LEN];
        s32 ie_offset = 0;
        s32 bssidx = 0;
@@ -3970,10 +3979,24 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
                } else {
                        WL_ERR(("No P2PIE in beacon \n"));
                }
+               /* find the WFD IEs */
+               if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) {
+               /* Total length of P2P Information Element */
+               wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id);
+               if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) {
+                       memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len);
+               } else {
+                               WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n",
+                               wpsie_len, p2pie_len, wfdie_len));
+                               wfdie_len = 0;
+                       }
+               } else {
+                       WL_ERR(("No WFDIE in beacon \n"));
+               }
                /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
                wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
                wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
-                       beacon_ie, wpsie_len + p2pie_len);
+                       beacon_ie, wpsie_len + p2pie_len + wfdie_len);
 
                /* find the RSN_IE */
                if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
index cfa5ac3..a34c4ad 100644 (file)
@@ -829,6 +829,10 @@ exit:
 /* Check whether the given IE looks like WFA P2P IE. */
 #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
                (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+/* Check whether the given IE looks like WFA WFDisplay IE. */
+#define WFA_OUI_TYPE_WFD       0x0a    /* WiFi Display OUI TYPE */
+#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)     wl_cfgp2p_has_ie(ie, tlvs, len, \
+               (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
 /* Delete and Set a management vndr ie to firmware
  * Parameters:
  * @wl       : wl_private data
@@ -953,7 +957,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+                                       wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
                                        CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -979,7 +984,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss
                                ie_len = ie_buf[pos++];
                                if ((ie_id == DOT11_MNG_VS_ID) &&
                                   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
-                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+                                       wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) ||
+                                       wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) {
                                        CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
                                                "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
                                                ie_buf[pos+1], ie_buf[pos+2]));
@@ -1089,6 +1095,18 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
        }
        return NULL;
 }
+wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+{
+       bcm_tlv_t *ie;
+
+       while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+       if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
+                       return (wifi_wfd_ie_t *)ie;
+               }
+       }
+       return NULL;
+}
 
 static s32
 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
index be497c3..668198d 100644 (file)
@@ -30,7 +30,7 @@
 
 struct wl_priv;
 extern u32 wl_dbg_level;
-
+typedef struct wifi_p2p_ie wifi_wfd_ie_t;
 /* Enumeration of the usages of the BSSCFGs used by the P2P Library.  Do not
  * confuse this with a bsscfg index.  This value is an index into the
  * saved_ie[] array of structures which in turn contains a bsscfg index field.
@@ -191,6 +191,9 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len);
 extern wifi_p2p_ie_t *
 wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
 
+extern wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(u8 *parse, u32 len);
+
 extern s32
 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
             s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);