@@ -90,7 +90,8 @@ struct ieee802_11_elems {
90
90
u8 * ext_supp_rates ;
91
91
u8 * wmm_info ;
92
92
u8 * wmm_param ;
93
-
93
+ u8 * ht_cap_elem ;
94
+ u8 * ht_info_elem ;
94
95
/* length of them, respectively */
95
96
u8 ssid_len ;
96
97
u8 supp_rates_len ;
@@ -106,6 +107,8 @@ struct ieee802_11_elems {
106
107
u8 ext_supp_rates_len ;
107
108
u8 wmm_info_len ;
108
109
u8 wmm_param_len ;
110
+ u8 ht_cap_elem_len ;
111
+ u8 ht_info_elem_len ;
109
112
};
110
113
111
114
static void ieee802_11_parse_elems (u8 * start , size_t len ,
@@ -190,6 +193,14 @@ static void ieee802_11_parse_elems(u8 *start, size_t len,
190
193
elems -> ext_supp_rates = pos ;
191
194
elems -> ext_supp_rates_len = elen ;
192
195
break ;
196
+ case WLAN_EID_HT_CAPABILITY :
197
+ elems -> ht_cap_elem = pos ;
198
+ elems -> ht_cap_elem_len = elen ;
199
+ break ;
200
+ case WLAN_EID_HT_EXTRA_INFO :
201
+ elems -> ht_info_elem = pos ;
202
+ elems -> ht_info_elem_len = elen ;
203
+ break ;
193
204
default :
194
205
break ;
195
206
}
@@ -332,6 +343,51 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
332
343
ieee80211_erp_info_change_notify (dev , changes );
333
344
}
334
345
346
+ int ieee80211_ht_cap_ie_to_ht_info (struct ieee80211_ht_cap * ht_cap_ie ,
347
+ struct ieee80211_ht_info * ht_info )
348
+ {
349
+
350
+ if (ht_info == NULL )
351
+ return - EINVAL ;
352
+
353
+ memset (ht_info , 0 , sizeof (* ht_info ));
354
+
355
+ if (ht_cap_ie ) {
356
+ u8 ampdu_info = ht_cap_ie -> ampdu_params_info ;
357
+
358
+ ht_info -> ht_supported = 1 ;
359
+ ht_info -> cap = le16_to_cpu (ht_cap_ie -> cap_info );
360
+ ht_info -> ampdu_factor =
361
+ ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR ;
362
+ ht_info -> ampdu_density =
363
+ (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY ) >> 2 ;
364
+ memcpy (ht_info -> supp_mcs_set , ht_cap_ie -> supp_mcs_set , 16 );
365
+ } else
366
+ ht_info -> ht_supported = 0 ;
367
+
368
+ return 0 ;
369
+ }
370
+
371
+ int ieee80211_ht_addt_info_ie_to_ht_bss_info (
372
+ struct ieee80211_ht_addt_info * ht_add_info_ie ,
373
+ struct ieee80211_ht_bss_info * bss_info )
374
+ {
375
+ if (bss_info == NULL )
376
+ return - EINVAL ;
377
+
378
+ memset (bss_info , 0 , sizeof (* bss_info ));
379
+
380
+ if (ht_add_info_ie ) {
381
+ u16 op_mode ;
382
+ op_mode = le16_to_cpu (ht_add_info_ie -> operation_mode );
383
+
384
+ bss_info -> primary_channel = ht_add_info_ie -> control_chan ;
385
+ bss_info -> bss_cap = ht_add_info_ie -> ht_param ;
386
+ bss_info -> bss_op_mode = (u8 )(op_mode & 0xff );
387
+ }
388
+
389
+ return 0 ;
390
+ }
335
391
336
392
static void ieee80211_sta_send_associnfo (struct net_device * dev ,
337
393
struct ieee80211_if_sta * ifsta )
@@ -630,6 +686,19 @@ static void ieee80211_send_assoc(struct net_device *dev,
630
686
* pos ++ = 1 ; /* WME ver */
631
687
* pos ++ = 0 ;
632
688
}
689
+ /* wmm support is a must to HT */
690
+ if (wmm && mode -> ht_info .ht_supported ) {
691
+ __le16 tmp = cpu_to_le16 (mode -> ht_info .cap );
692
+ pos = skb_put (skb , sizeof (struct ieee80211_ht_cap )+2 );
693
+ * pos ++ = WLAN_EID_HT_CAPABILITY ;
694
+ * pos ++ = sizeof (struct ieee80211_ht_cap );
695
+ memset (pos , 0 , sizeof (struct ieee80211_ht_cap ));
696
+ memcpy (pos , & tmp , sizeof (u16 ));
697
+ pos += sizeof (u16 );
698
+ * pos ++ = (mode -> ht_info .ampdu_factor |
699
+ (mode -> ht_info .ampdu_density << 2 ));
700
+ memcpy (pos , mode -> ht_info .supp_mcs_set , 16 );
701
+ }
633
702
634
703
kfree (ifsta -> assocreq_ies );
635
704
ifsta -> assocreq_ies_len = (skb -> data + skb -> len ) - ies ;
@@ -1380,6 +1449,7 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
1380
1449
kfree (bss -> wpa_ie );
1381
1450
kfree (bss -> rsn_ie );
1382
1451
kfree (bss -> wmm_ie );
1452
+ kfree (bss -> ht_ie );
1383
1453
kfree (bss );
1384
1454
}
1385
1455
@@ -1637,7 +1707,22 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1637
1707
bss -> wmm_ie = NULL ;
1638
1708
bss -> wmm_ie_len = 0 ;
1639
1709
}
1640
-
1710
+ if (elems .ht_cap_elem &&
1711
+ (!bss -> ht_ie || bss -> ht_ie_len != elems .ht_cap_elem_len ||
1712
+ memcmp (bss -> ht_ie , elems .ht_cap_elem , elems .ht_cap_elem_len ))) {
1713
+ kfree (bss -> ht_ie );
1714
+ bss -> ht_ie = kmalloc (elems .ht_cap_elem_len + 2 , GFP_ATOMIC );
1715
+ if (bss -> ht_ie ) {
1716
+ memcpy (bss -> ht_ie , elems .ht_cap_elem - 2 ,
1717
+ elems .ht_cap_elem_len + 2 );
1718
+ bss -> ht_ie_len = elems .ht_cap_elem_len + 2 ;
1719
+ } else
1720
+ bss -> ht_ie_len = 0 ;
1721
+ } else if (!elems .ht_cap_elem && bss -> ht_ie ) {
1722
+ kfree (bss -> ht_ie );
1723
+ bss -> ht_ie = NULL ;
1724
+ bss -> ht_ie_len = 0 ;
1725
+ }
1641
1726
1642
1727
bss -> hw_mode = rx_status -> phymode ;
1643
1728
bss -> freq = rx_status -> freq ;
0 commit comments