HDD: Pass Operating Channel and Class information to the firmware.

This commit ensures to pass the TDLS peer's operating channel to the
firmware in LinkEstablishRequest.

Change-Id: I1d13898ccbe5cc6387ef97e00f46ea17b3b9b19d
CRs-Fixed: 610536
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 6f3a1f8..df5f77c 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -11,6 +11,9 @@
 
 \brief       Linux HDD TDLS include file
 
+Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+All Rights Reserved.
+Qualcomm Atheros Confidential and Proprietary.
 ==========================================================================*/
 
 #define MAX_NUM_TDLS_PEER           3
@@ -145,6 +148,11 @@
     tANI_U8     uapsdQueues;
     tANI_U8     maxSp;
     tANI_U8     isBufSta;
+    tANI_U8     isOffChannelSupported;
+    tANI_U8     supported_channels_len;
+    tANI_U8     supported_channels[SIR_MAC_MAX_SUPP_CHANNELS];
+    tANI_U8     supported_oper_classes_len;
+    tANI_U8     supported_oper_classes[SIR_MAC_MAX_SUPP_OPER_CLASSES];
     vos_timer_t     peerIdleTimer;
     vos_timer_t     initiatorWaitTimeoutTimer;
     tANI_BOOLEAN isForcedPeer;
@@ -189,9 +197,9 @@
 
 int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter,
                                 u8 *mac,
-                                tANI_U8 uapsdQueues,
-                                tANI_U8 maxSp,
-                                tANI_BOOLEAN isBufSta);
+                                tCsrStaParams *StaParams,
+                                tANI_BOOLEAN isBufSta,
+                                tANI_BOOLEAN isOffChannelSupported);
 
 int wlan_hdd_tdls_set_rssi(hdd_adapter_t *pAdapter, u8 *mac, tANI_S8 rxRssi);
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index fd671f3..ce7a01a 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -118,6 +118,8 @@
 #define WLAN_AKM_SUITE_FT_PSK           0x000FAC04
 #endif
 
+#define HDD_CHANNEL_14 14
+
 static const u32 hdd_cipher_suites[] =
 {
     WLAN_CIPHER_SUITE_WEP40,
@@ -3345,6 +3347,7 @@
 #ifdef FEATURE_WLAN_TDLS
     tCsrStaParams StaParams = {0};
     tANI_U8 isBufSta = 0;
+    tANI_U8 isOffChannelSupported = 0;
 #endif
     ENTER();
 
@@ -3398,6 +3401,36 @@
             StaParams.uapsd_queues = params->uapsd_queues;
             StaParams.max_sp = params->max_sp;
 
+            /* Convert (first channel , number of channels) tuple to
+             * the total list of channels. This goes with the assumption
+             * that if the first channel is < 14, then the next channels
+             * are an incremental of 1 else an incremental of 4 till the number
+             * of channels.
+             */
+            if (0 != params->supported_channels_len) {
+                int i = 0,j = 0,k = 0, no_of_channels = 0 ;
+                for ( i = 0 ; i < params->supported_channels_len ; i+=2)
+                {
+                    int wifi_chan_index;
+                    StaParams.supported_channels[j] = params->supported_channels[i];
+                    wifi_chan_index =
+                        ((StaParams.supported_channels[j] <= HDD_CHANNEL_14 ) ? 1 : 4 );
+                    no_of_channels = params->supported_channels[i+1];
+                    for(k=1; k <= no_of_channels; k++)
+                    {
+                        StaParams.supported_channels[j+1] =
+                              StaParams.supported_channels[j] + wifi_chan_index;
+                        j+=1;
+                    }
+                }
+                StaParams.supported_channels_len = j;
+            }
+            vos_mem_copy(StaParams.supported_oper_classes,
+                         params->supported_oper_classes,
+                         params->supported_oper_classes_len);
+            StaParams.supported_oper_classes_len  =
+                                             params->supported_oper_classes_len;
+
             if (0 != params->ext_capab_len)
                 vos_mem_copy(StaParams.extn_capability, params->ext_capab,
                              sizeof(StaParams.extn_capability));
@@ -3443,9 +3476,15 @@
                 if ((1<<4) & StaParams.extn_capability[3]) {
                     isBufSta = 1;
                 }
+                /* TDLS Channel Switching Support */
+                if ((1<<6) & StaParams.extn_capability[3]) {
+                    isOffChannelSupported = 1;
+                }
             }
-            status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac, params->uapsd_queues,
-                                                  params->max_sp, isBufSta);
+            status = wlan_hdd_tdls_set_peer_caps( pAdapter, mac,
+                                                  &StaParams, isBufSta,
+                                                  isOffChannelSupported);
+
             if (VOS_STATUS_SUCCESS != status) {
                 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                           "%s: wlan_hdd_tdls_set_peer_caps failed!", __func__);
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index e3d0b69..35c6dc9 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -1096,9 +1096,9 @@
 
 int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter,
                                 u8 *mac,
-                                tANI_U8 uapsdQueues,
-                                tANI_U8 maxSp,
-                                tANI_BOOLEAN isBufSta)
+                                tCsrStaParams *StaParams,
+                                tANI_BOOLEAN isBufSta,
+                                tANI_BOOLEAN isOffChannelSupported)
 {
     hddTdlsPeer_t *curr_peer;
 
@@ -1110,9 +1110,24 @@
         return -1;
     }
 
-    curr_peer->uapsdQueues = uapsdQueues;
-    curr_peer->maxSp = maxSp;
+    curr_peer->uapsdQueues = StaParams->uapsd_queues;
+    curr_peer->maxSp = StaParams->max_sp;
     curr_peer->isBufSta = isBufSta;
+    curr_peer->isOffChannelSupported = isOffChannelSupported;
+
+    vos_mem_copy(curr_peer->supported_channels,
+                 StaParams->supported_channels,
+                 StaParams->supported_channels_len);
+
+    curr_peer->supported_channels_len =
+               StaParams->supported_channels_len;
+
+    vos_mem_copy(curr_peer->supported_oper_classes,
+                 StaParams->supported_oper_classes,
+                 StaParams->supported_oper_classes_len);
+
+    curr_peer->supported_oper_classes_len =
+               StaParams->supported_oper_classes_len;
     return 0;
 }
 
@@ -1133,6 +1148,22 @@
     tdlsLinkEstablishParams->uapsdQueues = curr_peer->uapsdQueues;
     tdlsLinkEstablishParams->maxSp = curr_peer->maxSp;
     tdlsLinkEstablishParams->isBufSta = curr_peer->isBufSta;
+    tdlsLinkEstablishParams->isOffChannelSupported =
+                                 curr_peer->isOffChannelSupported;
+
+    vos_mem_copy(tdlsLinkEstablishParams->supportedChannels,
+                 curr_peer->supported_channels,
+                 curr_peer->supported_channels_len);
+
+    tdlsLinkEstablishParams->supportedChannelsLen =
+                 curr_peer->supported_channels_len;
+
+    vos_mem_copy(tdlsLinkEstablishParams->supportedOperClasses,
+                 curr_peer->supported_oper_classes,
+                 curr_peer->supported_oper_classes_len);
+
+    tdlsLinkEstablishParams->supportedOperClassesLen =
+                 curr_peer->supported_oper_classes_len;
     return 0;
 }