static void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
{
-#define PRINT_HT_CAP(_cond, _str) \
- do { \
- if (_cond) \
- printf("\t\t\t" _str "\n"); \
- } while (0)
- struct ht_cap_data {
- __u16 cap;
- __u8 ampdu_params;
- struct {
- __u8 rx_mcs_bitmask[10]; /* last 3 bits reserved */
- __u16 max_rx_rate_1mbps: 10,
- reserved_0: 6;
- __u8 tx_rx_mcs_defined:1,
- tx_rx_mcs_not_equal:1,
- tx_max_streams:2,
- tx_unequal_modulation:1,
- reserved_1:3; /* 3 reserved bits here */
- __u8 reserved_2[3]; /* 24 reserved bits here = 27 */
- } mcs_set;
- __u16 ht_extend_cap;
- __u32 tx_beamform_cap;
- __u8 asel_cap;
- } __attribute__((packed)) ht_cap;
- struct ht_cap_data *htc = &ht_cap;
- __u8 ampdu_exponent, ampdu_spacing, bit;
- __u32 i;
- bool tx_rx_mcs_equal = false;
-
if (len != 26) {
printf("\n\t\tHT Capability IE len != expected 26 bytes, skipping parse\n");
return;
}
-
- memcpy(&ht_cap, data, 26);
-
- printf("\n\t\tCapabilities: %#.4x\n", htc->cap);
-
- PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP");
- PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40");
- PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20");
-
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save");
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save");
- PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled");
-
- PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield");
- PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI");
- PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI");
- PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC");
-
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams");
- PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams");
-
- PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack");
-
- PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: 3839 bytes");
- PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: 7935 bytes");
-
- /*
- * For beacons and probe response this would mean the BSS
- * does or does not allow the usage of DSSS/CCK HT40.
- * Otherwise it means the STA does or does not use
- * DSSS/CCK HT40.
- */
- PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40");
- PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40");
-
- /* BIT(13) is reserved */
-
- PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant");
-
- PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection");
-
- ampdu_exponent = htc->ampdu_params & 0x3;
- print_ampdu_length(ampdu_exponent);
-
- ampdu_spacing = (htc->ampdu_params >> 2) & 0x3;
- print_ampdu_spacing(ampdu_spacing);
-
- /* This is the whole MCS set, which is 16 bytes */
- printf("\t\tMCS set:");
- data+=2;
- print_mcs_set(data);
printf("\n");
-
- if (htc->mcs_set.tx_rx_mcs_defined && htc->mcs_set.tx_rx_mcs_not_equal)
- tx_rx_mcs_equal = true;
- if (tx_rx_mcs_equal)
- printf("\t\tSupported TX/RX MCS Indexes:\n");
- else
- printf("\t\tSupported RX MCS Indexes:\n");
- /*
- * Parses the RX MCS rates. Only 10 bits correspond to actual MCS rates
- * MCS [0-76]
- */
- for (i = 0; i < 10; i++) {
- for (bit = 0; bit < 8; bit++) {
- /* Only bits 0-76 are valid, bits 76-79 are reserved */
- if (((i * 8) + bit) > 76)
- break;
- if (htc->mcs_set.rx_mcs_bitmask[i] & BIT(bit))
- printf("\t\t\tMCS Index %d\n",
- (i * 8) + bit);
- }
- }
-
- if (!htc->mcs_set.tx_rx_mcs_defined) {
- /* This is actually quite common */
- printf("\t\tNo TX MCS set defined\n");
- goto out;
- }
-
- if (htc->mcs_set.tx_rx_mcs_not_equal) {
- printf("\t\tMaximum supported TX spatial streams: %d\n",
- htc->mcs_set.tx_max_streams);
- printf("\t\tTX unequal modulation ");
- if (htc->mcs_set.tx_unequal_modulation)
- printf("supported\n");
- else
- printf("unsupported\n");
- }
-
-out:
- return;
+ print_ht_capability(data[0] | (data[1] << 8));
+ print_ampdu_length(data[2] & 3);
+ print_ampdu_spacing((data[2] >> 2) & 3);
+ print_ht_mcs(data + 3);
}
static void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)