1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * IEEE 802.11 S1G definitions 4 * 5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 6 * <jkmaline@cc.hut.fi> 7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> 8 * Copyright (c) 2005, Devicescape Software, Inc. 9 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> 10 * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH 11 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH 12 * Copyright (c) 2018 - 2025 Intel Corporation 13 */ 14 15 #ifndef LINUX_IEEE80211_S1G_H 16 #define LINUX_IEEE80211_S1G_H 17 18 #include <linux/types.h> 19 #include <linux/if_ether.h> 20 21 /* bits unique to S1G beacon frame control */ 22 #define IEEE80211_S1G_BCN_NEXT_TBTT 0x100 23 #define IEEE80211_S1G_BCN_CSSID 0x200 24 #define IEEE80211_S1G_BCN_ANO 0x400 25 26 /* see 802.11ah-2016 9.9 NDP CMAC frames */ 27 #define IEEE80211_S1G_1MHZ_NDP_BITS 25 28 #define IEEE80211_S1G_1MHZ_NDP_BYTES 4 29 #define IEEE80211_S1G_2MHZ_NDP_BITS 37 30 #define IEEE80211_S1G_2MHZ_NDP_BYTES 5 31 32 /** 33 * ieee80211_is_s1g_beacon - check if IEEE80211_FTYPE_EXT && 34 * IEEE80211_STYPE_S1G_BEACON 35 * @fc: frame control bytes in little-endian byteorder 36 * Return: whether or not the frame is an S1G beacon 37 */ 38 static inline bool ieee80211_is_s1g_beacon(__le16 fc) 39 { 40 return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | 41 IEEE80211_FCTL_STYPE)) == 42 cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON); 43 } 44 45 /** 46 * ieee80211_s1g_has_next_tbtt - check if IEEE80211_S1G_BCN_NEXT_TBTT 47 * @fc: frame control bytes in little-endian byteorder 48 * Return: whether or not the frame contains the variable-length 49 * next TBTT field 50 */ 51 static inline bool ieee80211_s1g_has_next_tbtt(__le16 fc) 52 { 53 return ieee80211_is_s1g_beacon(fc) && 54 (fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT)); 55 } 56 57 /** 58 * ieee80211_s1g_has_ano - check if IEEE80211_S1G_BCN_ANO 59 * @fc: frame control bytes in little-endian byteorder 60 * Return: whether or not the frame contains the variable-length 61 * ANO field 62 */ 63 static inline bool ieee80211_s1g_has_ano(__le16 fc) 64 { 65 return ieee80211_is_s1g_beacon(fc) && 66 (fc & cpu_to_le16(IEEE80211_S1G_BCN_ANO)); 67 } 68 69 /** 70 * ieee80211_s1g_has_cssid - check if IEEE80211_S1G_BCN_CSSID 71 * @fc: frame control bytes in little-endian byteorder 72 * Return: whether or not the frame contains the variable-length 73 * compressed SSID field 74 */ 75 static inline bool ieee80211_s1g_has_cssid(__le16 fc) 76 { 77 return ieee80211_is_s1g_beacon(fc) && 78 (fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID)); 79 } 80 81 /** 82 * enum ieee80211_s1g_chanwidth - S1G channel widths 83 * These are defined in IEEE802.11-2016ah Table 10-20 84 * as BSS Channel Width 85 * 86 * @IEEE80211_S1G_CHANWIDTH_1MHZ: 1MHz operating channel 87 * @IEEE80211_S1G_CHANWIDTH_2MHZ: 2MHz operating channel 88 * @IEEE80211_S1G_CHANWIDTH_4MHZ: 4MHz operating channel 89 * @IEEE80211_S1G_CHANWIDTH_8MHZ: 8MHz operating channel 90 * @IEEE80211_S1G_CHANWIDTH_16MHZ: 16MHz operating channel 91 */ 92 enum ieee80211_s1g_chanwidth { 93 IEEE80211_S1G_CHANWIDTH_1MHZ = 0, 94 IEEE80211_S1G_CHANWIDTH_2MHZ = 1, 95 IEEE80211_S1G_CHANWIDTH_4MHZ = 3, 96 IEEE80211_S1G_CHANWIDTH_8MHZ = 7, 97 IEEE80211_S1G_CHANWIDTH_16MHZ = 15, 98 }; 99 100 /** 101 * enum ieee80211_s1g_pri_chanwidth - S1G primary channel widths 102 * described in IEEE80211-2024 Table 10-39. 103 * 104 * @IEEE80211_S1G_PRI_CHANWIDTH_2MHZ: 2MHz primary channel 105 * @IEEE80211_S1G_PRI_CHANWIDTH_1MHZ: 1MHz primary channel 106 */ 107 enum ieee80211_s1g_pri_chanwidth { 108 IEEE80211_S1G_PRI_CHANWIDTH_2MHZ = 0, 109 IEEE80211_S1G_PRI_CHANWIDTH_1MHZ = 1, 110 }; 111 112 /** 113 * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element 114 * @compat_info: Compatibility Information 115 * @beacon_int: Beacon Interval 116 * @tsf_completion: TSF Completion 117 * 118 * This structure represents the payload of the "S1G Beacon 119 * Compatibility element" as described in IEEE Std 802.11-2020 section 120 * 9.4.2.196. 121 */ 122 struct ieee80211_s1g_bcn_compat_ie { 123 __le16 compat_info; 124 __le16 beacon_int; 125 __le32 tsf_completion; 126 } __packed; 127 128 /** 129 * struct ieee80211_s1g_oper_ie - S1G Operation element 130 * @ch_width: S1G Operation Information Channel Width 131 * @oper_class: S1G Operation Information Operating Class 132 * @primary_ch: S1G Operation Information Primary Channel Number 133 * @oper_ch: S1G Operation Information Channel Center Frequency 134 * @basic_mcs_nss: Basic S1G-MCS and NSS Set 135 * 136 * This structure represents the payload of the "S1G Operation 137 * element" as described in IEEE Std 802.11-2020 section 9.4.2.212. 138 */ 139 struct ieee80211_s1g_oper_ie { 140 u8 ch_width; 141 u8 oper_class; 142 u8 primary_ch; 143 u8 oper_ch; 144 __le16 basic_mcs_nss; 145 } __packed; 146 147 /** 148 * struct ieee80211_aid_response_ie - AID Response element 149 * @aid: AID/Group AID 150 * @switch_count: AID Switch Count 151 * @response_int: AID Response Interval 152 * 153 * This structure represents the payload of the "AID Response element" 154 * as described in IEEE Std 802.11-2020 section 9.4.2.194. 155 */ 156 struct ieee80211_aid_response_ie { 157 __le16 aid; 158 u8 switch_count; 159 __le16 response_int; 160 } __packed; 161 162 struct ieee80211_s1g_cap { 163 u8 capab_info[10]; 164 u8 supp_mcs_nss[5]; 165 } __packed; 166 167 /** 168 * ieee80211_s1g_optional_len - determine length of optional S1G beacon fields 169 * @fc: frame control bytes in little-endian byteorder 170 * Return: total length in bytes of the optional fixed-length fields 171 * 172 * S1G beacons may contain up to three optional fixed-length fields that 173 * precede the variable-length elements. Whether these fields are present 174 * is indicated by flags in the frame control field. 175 * 176 * From IEEE 802.11-2024 section 9.3.4.3: 177 * - Next TBTT field may be 0 or 3 bytes 178 * - Short SSID field may be 0 or 4 bytes 179 * - Access Network Options (ANO) field may be 0 or 1 byte 180 */ 181 static inline size_t 182 ieee80211_s1g_optional_len(__le16 fc) 183 { 184 size_t len = 0; 185 186 if (ieee80211_s1g_has_next_tbtt(fc)) 187 len += 3; 188 189 if (ieee80211_s1g_has_cssid(fc)) 190 len += 4; 191 192 if (ieee80211_s1g_has_ano(fc)) 193 len += 1; 194 195 return len; 196 } 197 198 /* S1G Capabilities Information field */ 199 #define IEEE80211_S1G_CAPABILITY_LEN 15 200 201 #define S1G_CAP0_S1G_LONG BIT(0) 202 #define S1G_CAP0_SGI_1MHZ BIT(1) 203 #define S1G_CAP0_SGI_2MHZ BIT(2) 204 #define S1G_CAP0_SGI_4MHZ BIT(3) 205 #define S1G_CAP0_SGI_8MHZ BIT(4) 206 #define S1G_CAP0_SGI_16MHZ BIT(5) 207 #define S1G_CAP0_SUPP_CH_WIDTH GENMASK(7, 6) 208 209 #define S1G_SUPP_CH_WIDTH_2 0 210 #define S1G_SUPP_CH_WIDTH_4 1 211 #define S1G_SUPP_CH_WIDTH_8 2 212 #define S1G_SUPP_CH_WIDTH_16 3 213 #define S1G_SUPP_CH_WIDTH_MAX(cap) ((1 << FIELD_GET(S1G_CAP0_SUPP_CH_WIDTH, \ 214 cap[0])) << 1) 215 216 #define S1G_CAP1_RX_LDPC BIT(0) 217 #define S1G_CAP1_TX_STBC BIT(1) 218 #define S1G_CAP1_RX_STBC BIT(2) 219 #define S1G_CAP1_SU_BFER BIT(3) 220 #define S1G_CAP1_SU_BFEE BIT(4) 221 #define S1G_CAP1_BFEE_STS GENMASK(7, 5) 222 223 #define S1G_CAP2_SOUNDING_DIMENSIONS GENMASK(2, 0) 224 #define S1G_CAP2_MU_BFER BIT(3) 225 #define S1G_CAP2_MU_BFEE BIT(4) 226 #define S1G_CAP2_PLUS_HTC_VHT BIT(5) 227 #define S1G_CAP2_TRAVELING_PILOT GENMASK(7, 6) 228 229 #define S1G_CAP3_RD_RESPONDER BIT(0) 230 #define S1G_CAP3_HT_DELAYED_BA BIT(1) 231 #define S1G_CAP3_MAX_MPDU_LEN BIT(2) 232 #define S1G_CAP3_MAX_AMPDU_LEN_EXP GENMASK(4, 3) 233 #define S1G_CAP3_MIN_MPDU_START GENMASK(7, 5) 234 235 #define S1G_CAP4_UPLINK_SYNC BIT(0) 236 #define S1G_CAP4_DYNAMIC_AID BIT(1) 237 #define S1G_CAP4_BAT BIT(2) 238 #define S1G_CAP4_TIME_ADE BIT(3) 239 #define S1G_CAP4_NON_TIM BIT(4) 240 #define S1G_CAP4_GROUP_AID BIT(5) 241 #define S1G_CAP4_STA_TYPE GENMASK(7, 6) 242 243 #define S1G_CAP5_CENT_AUTH_CONTROL BIT(0) 244 #define S1G_CAP5_DIST_AUTH_CONTROL BIT(1) 245 #define S1G_CAP5_AMSDU BIT(2) 246 #define S1G_CAP5_AMPDU BIT(3) 247 #define S1G_CAP5_ASYMMETRIC_BA BIT(4) 248 #define S1G_CAP5_FLOW_CONTROL BIT(5) 249 #define S1G_CAP5_SECTORIZED_BEAM GENMASK(7, 6) 250 251 #define S1G_CAP6_OBSS_MITIGATION BIT(0) 252 #define S1G_CAP6_FRAGMENT_BA BIT(1) 253 #define S1G_CAP6_NDP_PS_POLL BIT(2) 254 #define S1G_CAP6_RAW_OPERATION BIT(3) 255 #define S1G_CAP6_PAGE_SLICING BIT(4) 256 #define S1G_CAP6_TXOP_SHARING_IMP_ACK BIT(5) 257 #define S1G_CAP6_VHT_LINK_ADAPT GENMASK(7, 6) 258 259 #define S1G_CAP7_TACK_AS_PS_POLL BIT(0) 260 #define S1G_CAP7_DUP_1MHZ BIT(1) 261 #define S1G_CAP7_MCS_NEGOTIATION BIT(2) 262 #define S1G_CAP7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3) 263 #define S1G_CAP7_NDP_BFING_REPORT_POLL BIT(4) 264 #define S1G_CAP7_UNSOLICITED_DYN_AID BIT(5) 265 #define S1G_CAP7_SECTOR_TRAINING_OPERATION BIT(6) 266 #define S1G_CAP7_TEMP_PS_MODE_SWITCH BIT(7) 267 268 #define S1G_CAP8_TWT_GROUPING BIT(0) 269 #define S1G_CAP8_BDT BIT(1) 270 #define S1G_CAP8_COLOR GENMASK(4, 2) 271 #define S1G_CAP8_TWT_REQUEST BIT(5) 272 #define S1G_CAP8_TWT_RESPOND BIT(6) 273 #define S1G_CAP8_PV1_FRAME BIT(7) 274 275 #define S1G_CAP9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0) 276 277 #define S1G_OPER_CH_WIDTH_PRIMARY BIT(0) 278 #define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1) 279 #define S1G_OPER_CH_PRIMARY_LOCATION BIT(5) 280 281 #define S1G_2M_PRIMARY_LOCATION_LOWER 0 282 #define S1G_2M_PRIMARY_LOCATION_UPPER 1 283 284 #define LISTEN_INT_USF GENMASK(15, 14) 285 #define LISTEN_INT_UI GENMASK(13, 0) 286 287 #define IEEE80211_MAX_USF FIELD_MAX(LISTEN_INT_USF) 288 #define IEEE80211_MAX_UI FIELD_MAX(LISTEN_INT_UI) 289 290 /* S1G encoding types */ 291 #define IEEE80211_S1G_TIM_ENC_MODE_BLOCK 0 292 #define IEEE80211_S1G_TIM_ENC_MODE_SINGLE 1 293 #define IEEE80211_S1G_TIM_ENC_MODE_OLB 2 294 295 enum ieee80211_s1g_actioncode { 296 WLAN_S1G_AID_SWITCH_REQUEST, 297 WLAN_S1G_AID_SWITCH_RESPONSE, 298 WLAN_S1G_SYNC_CONTROL, 299 WLAN_S1G_STA_INFO_ANNOUNCE, 300 WLAN_S1G_EDCA_PARAM_SET, 301 WLAN_S1G_EL_OPERATION, 302 WLAN_S1G_TWT_SETUP, 303 WLAN_S1G_TWT_TEARDOWN, 304 WLAN_S1G_SECT_GROUP_ID_LIST, 305 WLAN_S1G_SECT_ID_FEEDBACK, 306 WLAN_S1G_TWT_INFORMATION = 11, 307 }; 308 309 /** 310 * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon 311 * @fc: frame control bytes in little-endian byteorder 312 * @variable: pointer to the beacon frame elements 313 * @variable_len: length of the frame elements 314 * Return: whether or not the frame is an S1G short beacon. As per 315 * IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall 316 * always be present as the first element in beacon frames generated at a 317 * TBTT (Target Beacon Transmission Time), so any frame not containing 318 * this element must have been generated at a TSBTT (Target Short Beacon 319 * Transmission Time) that is not a TBTT. Additionally, short beacons are 320 * prohibited from containing the S1G beacon compatibility element as per 321 * IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with 322 * either no elements or the first element is not the beacon compatibility 323 * element, we have a short beacon. 324 */ 325 static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable, 326 size_t variable_len) 327 { 328 if (!ieee80211_is_s1g_beacon(fc)) 329 return false; 330 331 /* 332 * If the frame does not contain at least 1 element (this is perfectly 333 * valid in a short beacon) and is an S1G beacon, we have a short 334 * beacon. 335 */ 336 if (variable_len < 2) 337 return true; 338 339 return variable[0] != WLAN_EID_S1G_BCN_COMPAT; 340 } 341 342 struct s1g_tim_aid { 343 u16 aid; 344 u8 target_blk; /* Target block index */ 345 u8 target_subblk; /* Target subblock index */ 346 u8 target_subblk_bit; /* Target subblock bit */ 347 }; 348 349 struct s1g_tim_enc_block { 350 u8 enc_mode; 351 bool inverse; 352 const u8 *ptr; 353 u8 len; 354 355 /* 356 * For an OLB encoded block that spans multiple blocks, this 357 * is the offset into the span described by that encoded block. 358 */ 359 u8 olb_blk_offset; 360 }; 361 362 /* 363 * Helper routines to quickly extract the length of an encoded block. Validation 364 * is also performed to ensure the length extracted lies within the TIM. 365 */ 366 367 static inline int ieee80211_s1g_len_bitmap(const u8 *ptr, const u8 *end) 368 { 369 u8 blkmap; 370 u8 n_subblks; 371 372 if (ptr >= end) 373 return -EINVAL; 374 375 blkmap = *ptr; 376 n_subblks = hweight8(blkmap); 377 378 if (ptr + 1 + n_subblks > end) 379 return -EINVAL; 380 381 return 1 + n_subblks; 382 } 383 384 static inline int ieee80211_s1g_len_single(const u8 *ptr, const u8 *end) 385 { 386 return (ptr + 1 > end) ? -EINVAL : 1; 387 } 388 389 static inline int ieee80211_s1g_len_olb(const u8 *ptr, const u8 *end) 390 { 391 if (ptr >= end) 392 return -EINVAL; 393 394 return (ptr + 1 + *ptr > end) ? -EINVAL : 1 + *ptr; 395 } 396 397 /* 398 * Enumerate all encoded blocks until we find the encoded block that describes 399 * our target AID. OLB is a special case as a single encoded block can describe 400 * multiple blocks as a single encoded block. 401 */ 402 static inline int ieee80211_s1g_find_target_block(struct s1g_tim_enc_block *enc, 403 const struct s1g_tim_aid *aid, 404 const u8 *ptr, const u8 *end) 405 { 406 /* need at least block-control octet */ 407 while (ptr + 1 <= end) { 408 u8 ctrl = *ptr++; 409 u8 mode = ctrl & 0x03; 410 bool contains, inverse = ctrl & BIT(2); 411 u8 span, blk_off = ctrl >> 3; 412 int len; 413 414 switch (mode) { 415 case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 416 len = ieee80211_s1g_len_bitmap(ptr, end); 417 contains = blk_off == aid->target_blk; 418 break; 419 case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 420 len = ieee80211_s1g_len_single(ptr, end); 421 contains = blk_off == aid->target_blk; 422 break; 423 case IEEE80211_S1G_TIM_ENC_MODE_OLB: 424 len = ieee80211_s1g_len_olb(ptr, end); 425 /* 426 * An OLB encoded block can describe more then one 427 * block, meaning an encoded OLB block can span more 428 * then a single block. 429 */ 430 if (len > 0) { 431 /* Minus one for the length octet */ 432 span = DIV_ROUND_UP(len - 1, 8); 433 /* 434 * Check if our target block lies within the 435 * block span described by this encoded block. 436 */ 437 contains = (aid->target_blk >= blk_off) && 438 (aid->target_blk < blk_off + span); 439 } 440 break; 441 default: 442 return -EOPNOTSUPP; 443 } 444 445 if (len < 0) 446 return len; 447 448 if (contains) { 449 enc->enc_mode = mode; 450 enc->inverse = inverse; 451 enc->ptr = ptr; 452 enc->len = (u8)len; 453 enc->olb_blk_offset = blk_off; 454 return 0; 455 } 456 457 ptr += len; 458 } 459 460 return -ENOENT; 461 } 462 463 static inline bool ieee80211_s1g_parse_bitmap(struct s1g_tim_enc_block *enc, 464 struct s1g_tim_aid *aid) 465 { 466 const u8 *ptr = enc->ptr; 467 u8 blkmap = *ptr++; 468 469 /* 470 * If our block bitmap does not contain a set bit that corresponds 471 * to our AID, it could mean a variety of things depending on if 472 * the encoding mode is inverted or not. 473 * 474 * 1. If inverted, it means the entire subblock is present and hence 475 * our AID has been set. 476 * 2. If not inverted, it means our subblock is not present and hence 477 * it is all zero meaning our AID is not set. 478 */ 479 if (!(blkmap & BIT(aid->target_subblk))) 480 return enc->inverse; 481 482 /* 483 * Increment ptr by the number of set subblocks that appear before our 484 * target subblock. If our target subblock is 0, do nothing as ptr 485 * already points to our target subblock. 486 */ 487 if (aid->target_subblk) 488 ptr += hweight8(blkmap & GENMASK(aid->target_subblk - 1, 0)); 489 490 return !!(*ptr & BIT(aid->target_subblk_bit)) ^ enc->inverse; 491 } 492 493 static inline bool ieee80211_s1g_parse_single(struct s1g_tim_enc_block *enc, 494 struct s1g_tim_aid *aid) 495 { 496 /* 497 * Single AID mode describes, as the name suggests, a single AID 498 * within the block described by the encoded block. The octet 499 * contains the 6 LSBs of the AID described in the block. The other 500 * 2 bits are reserved. When inversed, every single AID described 501 * by the current block have buffered traffic except for the AID 502 * described in the single AID octet. 503 */ 504 return ((*enc->ptr & 0x3f) == (aid->aid & 0x3f)) ^ enc->inverse; 505 } 506 507 static inline bool ieee80211_s1g_parse_olb(struct s1g_tim_enc_block *enc, 508 struct s1g_tim_aid *aid) 509 { 510 const u8 *ptr = enc->ptr; 511 u8 blk_len = *ptr++; 512 /* 513 * Given an OLB encoded block that describes multiple blocks, 514 * calculate the offset into the span. Then calculate the 515 * subblock location normally. 516 */ 517 u16 span_offset = aid->target_blk - enc->olb_blk_offset; 518 u16 subblk_idx = span_offset * 8 + aid->target_subblk; 519 520 if (subblk_idx >= blk_len) 521 return enc->inverse; 522 523 return !!(ptr[subblk_idx] & BIT(aid->target_subblk_bit)) ^ enc->inverse; 524 } 525 526 /* 527 * An S1G PVB has 3 non optional encoding types, each that can be inverted. 528 * An S1G PVB is constructed with zero or more encoded block subfields. Each 529 * encoded block represents a single "block" of AIDs (64), and each encoded 530 * block can contain one of the 3 encoding types alongside a single bit for 531 * whether the bits should be inverted. 532 * 533 * As the standard makes no guarantee about the ordering of encoded blocks, 534 * we must parse every encoded block in the worst case scenario given an 535 * AID that lies within the last block. 536 */ 537 static inline bool ieee80211_s1g_check_tim(const struct ieee80211_tim_ie *tim, 538 u8 tim_len, u16 aid) 539 { 540 int err; 541 struct s1g_tim_aid target_aid; 542 struct s1g_tim_enc_block enc_blk; 543 544 if (tim_len < 3) 545 return false; 546 547 target_aid.aid = aid; 548 target_aid.target_blk = (aid >> 6) & 0x1f; 549 target_aid.target_subblk = (aid >> 3) & 0x7; 550 target_aid.target_subblk_bit = aid & 0x7; 551 552 /* 553 * Find our AIDs target encoded block and fill &enc_blk with the 554 * encoded blocks information. If no entry is found or an error 555 * occurs return false. 556 */ 557 err = ieee80211_s1g_find_target_block(&enc_blk, &target_aid, 558 tim->virtual_map, 559 (const u8 *)tim + tim_len + 2); 560 if (err) 561 return false; 562 563 switch (enc_blk.enc_mode) { 564 case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 565 return ieee80211_s1g_parse_bitmap(&enc_blk, &target_aid); 566 case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 567 return ieee80211_s1g_parse_single(&enc_blk, &target_aid); 568 case IEEE80211_S1G_TIM_ENC_MODE_OLB: 569 return ieee80211_s1g_parse_olb(&enc_blk, &target_aid); 570 default: 571 return false; 572 } 573 } 574 575 #endif /* LINUX_IEEE80211_H */ 576