| 806 | } |
| 807 | |
| 808 | static int |
| 809 | maxrate(const struct ieee80211_scan_entry *se) |
| 810 | { |
| 811 | const struct ieee80211_ie_htcap *htcap = |
| 812 | (const struct ieee80211_ie_htcap *) se->se_ies.htcap_ie; |
| 813 | int rmax, r, i, txstream; |
| 814 | uint16_t caps; |
| 815 | uint8_t txparams; |
| 816 | |
| 817 | rmax = 0; |
| 818 | if (htcap != NULL) { |
| 819 | /* |
| 820 | * HT station; inspect supported MCS and then adjust |
| 821 | * rate by channel width. |
| 822 | */ |
| 823 | txparams = htcap->hc_mcsset[12]; |
| 824 | if (txparams & 0x3) { |
| 825 | /* |
| 826 | * TX MCS parameters defined and not equal to RX, |
| 827 | * extract the number of spartial streams and |
| 828 | * map it to the highest MCS rate. |
| 829 | */ |
| 830 | txstream = ((txparams & 0xc) >> 2) + 1; |
| 831 | i = txstream * 8 - 1; |
| 832 | } else |
| 833 | for (i = 31; i >= 0 && isclr(htcap->hc_mcsset, i); i--); |
| 834 | if (i >= 0) { |
| 835 | caps = le16dec(&htcap->hc_cap); |
| 836 | if ((caps & IEEE80211_HTCAP_CHWIDTH40) && |
| 837 | (caps & IEEE80211_HTCAP_SHORTGI40)) |
| 838 | rmax = ieee80211_htrates[i].ht40_rate_400ns; |
| 839 | else if (caps & IEEE80211_HTCAP_CHWIDTH40) |
| 840 | rmax = ieee80211_htrates[i].ht40_rate_800ns; |
| 841 | else if (caps & IEEE80211_HTCAP_SHORTGI20) |
| 842 | rmax = ieee80211_htrates[i].ht20_rate_400ns; |
| 843 | else |
| 844 | rmax = ieee80211_htrates[i].ht20_rate_800ns; |
| 845 | } |
| 846 | } |
| 847 | for (i = 0; i < se->se_rates[1]; i++) { |
| 848 | r = se->se_rates[2+i] & IEEE80211_RATE_VAL; |
| 849 | if (r > rmax) |
| 850 | rmax = r; |
| 851 | } |
| 852 | for (i = 0; i < se->se_xrates[1]; i++) { |
| 853 | r = se->se_xrates[2+i] & IEEE80211_RATE_VAL; |
| 854 | if (r > rmax) |
| 855 | rmax = r; |
| 856 | } |
| 857 | return rmax; |
| 858 | } |
| 859 | |
| 860 | /* |
| 861 | * Compare the capabilities of two entries and decide which is |
no test coverage detected