2 ******************************************************************************
6 * Copyright (C) ESWIN 2015-2020
8 ******************************************************************************
13 ******************************************************************************
16 #include "ecrnx_tdls.h"
17 #include "ecrnx_compat.h"
20 * FUNCTION DEFINITIONS
21 ******************************************************************************
25 ecrnx_get_tdls_sta_capab(struct ecrnx_vif *ecrnx_vif, u16 status_code)
29 /* The capability will be 0 when sending a failure code */
33 if (ecrnx_vif->sta.ap->band != NL80211_BAND_2GHZ)
36 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
37 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
43 ecrnx_tdls_prepare_encap_data(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
44 const u8 *peer, u8 action_code, u8 dialog_token,
45 u16 status_code, struct sk_buff *skb)
47 struct ieee80211_tdls_data *tf;
48 tf = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_data) - sizeof(tf->u));
51 memcpy(tf->da, peer, ETH_ALEN);
52 memcpy(tf->sa, ecrnx_hw->wiphy->perm_addr, ETH_ALEN);
53 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
55 // set common TDLS info
56 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
57 tf->category = WLAN_CATEGORY_TDLS;
58 tf->action_code = action_code;
60 // set action specific TDLS info
61 switch (action_code) {
62 case WLAN_TDLS_SETUP_REQUEST:
63 skb_put(skb, sizeof(tf->u.setup_req));
64 tf->u.setup_req.dialog_token = dialog_token;
65 tf->u.setup_req.capability =
66 cpu_to_le16(ecrnx_get_tdls_sta_capab(ecrnx_vif, status_code));
69 case WLAN_TDLS_SETUP_RESPONSE:
70 skb_put(skb, sizeof(tf->u.setup_resp));
71 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
72 tf->u.setup_resp.dialog_token = dialog_token;
73 tf->u.setup_resp.capability =
74 cpu_to_le16(ecrnx_get_tdls_sta_capab(ecrnx_vif, status_code));
77 case WLAN_TDLS_SETUP_CONFIRM:
78 skb_put(skb, sizeof(tf->u.setup_cfm));
79 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
80 tf->u.setup_cfm.dialog_token = dialog_token;
83 case WLAN_TDLS_TEARDOWN:
84 skb_put(skb, sizeof(tf->u.teardown));
85 tf->u.teardown.reason_code = cpu_to_le16(status_code);
88 case WLAN_TDLS_DISCOVERY_REQUEST:
89 skb_put(skb, sizeof(tf->u.discover_req));
90 tf->u.discover_req.dialog_token = dialog_token;
101 ecrnx_prep_tdls_direct(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
102 const u8 *peer, u8 action_code, u8 dialog_token,
103 u16 status_code, struct sk_buff *skb)
105 struct ieee80211_mgmt *mgmt;
107 mgmt = (void *)skb_put(skb, 24);
109 memcpy(mgmt->da, peer, ETH_ALEN);
110 memcpy(mgmt->sa, ecrnx_hw->wiphy->perm_addr, ETH_ALEN);
111 memcpy(mgmt->bssid, ecrnx_vif->sta.ap->mac_addr, ETH_ALEN);
113 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
114 IEEE80211_STYPE_ACTION);
116 switch (action_code) {
117 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
118 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
119 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
120 mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
121 mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token;
122 mgmt->u.action.u.tdls_discover_resp.capability =
123 cpu_to_le16(ecrnx_get_tdls_sta_capab(ecrnx_vif, status_code));
133 ecrnx_add_srates_ie(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
137 struct ieee80211_supported_band *ecrnx_band_2GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
141 if (skb_tailroom(skb) < rates + 2)
144 pos = skb_put(skb, rates + 2);
145 *pos++ = WLAN_EID_SUPP_RATES;
147 for (i = 0; i < rates; i++) {
148 rate = ecrnx_band_2GHz->bitrates[i].bitrate;
149 rate = DIV_ROUND_UP(rate, 5);
157 ecrnx_add_ext_srates_ie(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
161 struct ieee80211_supported_band *ecrnx_band_2GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
163 exrates = ecrnx_band_2GHz->n_bitrates - 8;
165 if (skb_tailroom(skb) < exrates + 2)
168 pos = skb_put(skb, exrates + 2);
169 *pos++ = WLAN_EID_EXT_SUPP_RATES;
171 for (i = 8; i < (8+exrates); i++) {
172 rate = ecrnx_band_2GHz->bitrates[i].bitrate;
173 rate = DIV_ROUND_UP(rate, 5);
181 ecrnx_tdls_add_supp_channels(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
184 * Add possible channels for TDLS. These are channels that are allowed
189 u8 *pos = skb_put(skb, 2);
190 struct ieee80211_supported_band *ecrnx_band_2GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
191 #ifdef CONFIG_ECRNX_5G
192 struct ieee80211_supported_band *ecrnx_band_5GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
195 *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
198 * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
199 * this doesn't happen in real world scenarios.
202 /* 2GHz, with 5MHz spacing */
203 pos_subband = skb_put(skb, 2);
204 if (ecrnx_band_2GHz->n_channels > 0)
206 *pos_subband++ = ieee80211_frequency_to_channel(ecrnx_band_2GHz->channels[0].center_freq);
207 *pos_subband++ = ecrnx_band_2GHz->n_channels;
211 #ifdef CONFIG_ECRNX_5G
212 /* 5GHz, with 20MHz spacing */
213 pos_subband = skb_put(skb, 2);
214 if (ecrnx_band_5GHz->n_channels > 0)
216 *pos_subband++ = ieee80211_frequency_to_channel(ecrnx_band_5GHz->channels[0].center_freq);
217 *pos_subband++ = ecrnx_band_5GHz->n_channels;
223 *pos = 2 * subband_cnt;
227 ecrnx_tdls_add_ext_capab(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
229 u8 *pos = (void *)skb_put(skb, 7);
230 bool chan_switch = ecrnx_hw->wiphy->features &
231 NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
233 *pos++ = WLAN_EID_EXT_CAPABILITY;
234 *pos++ = 5; /* len */
238 *pos++ = WLAN_EXT_CAPA4_TDLS_BUFFER_STA |
239 (chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0);
240 *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
244 ecrnx_add_wmm_info_ie(struct sk_buff *skb, u8 qosinfo)
246 u8 *pos = (void *)skb_put(skb, 9);
248 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
249 *pos++ = 7; /* len */
250 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
253 *pos++ = 2; /* WME */
254 *pos++ = 0; /* WME info */
255 *pos++ = 1; /* WME ver */
256 *pos++ = qosinfo; /* U-APSD no in use */
259 /* translate numbering in the WMM parameter IE to the mac80211 notation */
260 static u8 ecrnx_ac_from_wmm(int ac)
278 ecrnx_add_wmm_param_ie(struct sk_buff *skb, u8 acm_bits, u32 *ac_params)
280 struct ieee80211_wmm_param_ie *wmm;
285 wmm = (void *)skb_put(skb, sizeof(struct ieee80211_wmm_param_ie));
286 memset(wmm, 0, sizeof(*wmm));
288 wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
289 wmm->len = sizeof(*wmm) - 2;
291 wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
294 wmm->oui_type = 2; /* WME */
295 wmm->oui_subtype = 1; /* WME param */
296 wmm->version = 1; /* WME ver */
297 wmm->qos_info = 0; /* U-APSD not in use */
300 * Use the EDCA parameters defined for the BSS, or default if the AP
301 * doesn't support it, as mandated by 802.11-2012 section 10.22.4
303 for (i = 0; i < AC_MAX; i++) {
304 j = ecrnx_ac_from_wmm(i);
305 cw_min = (ac_params[j] & 0xF0 ) >> 4;
306 cw_max = (ac_params[j] & 0xF00 ) >> 8;
307 acm = (acm_bits & (1 << j)) != 0;
309 wmm->ac[i].aci_aifsn = (i << 5) | (acm << 4) | (ac_params[j] & 0xF);
310 wmm->ac[i].cw = (cw_max << 4) | cw_min;
311 wmm->ac[i].txop_limit = (ac_params[j] & 0x0FFFF000 ) >> 12;
316 ecrnx_tdls_add_oper_classes(struct ecrnx_vif *ecrnx_vif, struct sk_buff *skb)
320 struct cfg80211_chan_def chan_def;
321 struct ieee80211_channel chan;
323 chan.band = ecrnx_vif->sta.ap->band;
324 chan.center_freq = ecrnx_vif->sta.ap->center_freq;
325 chan_def.chan = &chan;
326 chan_def.width = ecrnx_vif->sta.ap->width;
327 chan_def.center_freq1 = ecrnx_vif->sta.ap->center_freq1;
328 chan_def.center_freq2 = ecrnx_vif->sta.ap->center_freq2;
330 if (!ieee80211_chandef_to_operating_class(&chan_def, &op_class))
333 pos = skb_put(skb, 4);
334 *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES;
335 *pos++ = 2; /* len */
339 *pos++ = op_class; /* give current operating class as alternate too */
341 // need to add 5GHz classes?
345 ecrnx_ie_build_ht_cap(struct sk_buff *skb, struct ieee80211_sta_ht_cap *ht_cap,
351 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
352 *pos++ = WLAN_EID_HT_CAPABILITY;
353 *pos++ = sizeof(struct ieee80211_ht_cap);
354 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
356 /* capability flags */
357 tmp = cpu_to_le16(cap);
358 memcpy(pos, &tmp, sizeof(u16));
361 /* AMPDU parameters */
362 *pos++ = ht_cap->ampdu_factor |
363 (ht_cap->ampdu_density <<
364 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
367 memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs));
368 pos += sizeof(ht_cap->mcs);
370 /* extended capabilities */
371 pos += sizeof(__le16);
373 /* BF capabilities */
374 pos += sizeof(__le32);
376 /* antenna selection */
381 ecrnx_ie_build_vht_cap(struct sk_buff *skb, struct ieee80211_sta_vht_cap *vht_cap,
387 pos = skb_put(skb, 14);
389 *pos++ = WLAN_EID_VHT_CAPABILITY;
390 *pos++ = sizeof(struct ieee80211_vht_cap);
391 memset(pos, 0, sizeof(struct ieee80211_vht_cap));
393 /* capability flags */
394 tmp = cpu_to_le32(cap);
395 memcpy(pos, &tmp, sizeof(u32));
399 memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
400 pos += sizeof(vht_cap->vht_mcs);
404 ecrnx_tdls_add_bss_coex_ie(struct sk_buff *skb)
406 u8 *pos = (void *)skb_put(skb, 3);
408 *pos++ = WLAN_EID_BSS_COEX_2040;
409 *pos++ = 1; /* len */
411 *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
415 ecrnx_tdls_add_link_ie(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
416 struct sk_buff *skb, const u8 *peer,
419 struct ieee80211_tdls_lnkie *lnkid;
420 const u8 *init_addr, *rsp_addr;
423 init_addr = ecrnx_hw->wiphy->perm_addr;
427 rsp_addr = ecrnx_hw->wiphy->perm_addr;
430 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
432 lnkid->ie_type = WLAN_EID_LINK_ID;
433 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
435 memcpy(lnkid->bssid, ecrnx_vif->sta.ap->mac_addr, ETH_ALEN);
436 memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
437 memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
441 ecrnx_tdls_add_aid_ie(struct ecrnx_vif *ecrnx_vif, struct sk_buff *skb)
443 u8 *pos = (void *)skb_put(skb, 4);
445 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
446 *pos++ = WLAN_EID_AID;
450 *pos++ = 2; /* len */
451 *pos++ = ecrnx_vif->sta.ap->aid;
455 ecrnx_ie_build_ht_oper(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
456 u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
459 struct ieee80211_ht_operation *ht_oper;
460 /* Build HT Information */
461 *pos++ = WLAN_EID_HT_OPERATION;
462 *pos++ = sizeof(struct ieee80211_ht_operation);
463 ht_oper = (struct ieee80211_ht_operation *)pos;
464 ht_oper->primary_chan = ieee80211_frequency_to_channel(
465 ecrnx_vif->sta.ap->center_freq);
466 switch (ecrnx_vif->sta.ap->width) {
467 case NL80211_CHAN_WIDTH_160:
468 case NL80211_CHAN_WIDTH_80P80:
469 case NL80211_CHAN_WIDTH_80:
470 case NL80211_CHAN_WIDTH_40:
471 if (ecrnx_vif->sta.ap->center_freq1 > ecrnx_vif->sta.ap->center_freq)
472 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
474 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
477 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
480 if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
481 ecrnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20_NOHT &&
482 ecrnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20)
483 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
485 ht_oper->operation_mode = cpu_to_le16(prot_mode);
486 ht_oper->stbc_param = 0x0000;
488 /* It seems that Basic MCS set and Supported MCS set
489 are identical for the first 10 bytes */
490 memset(&ht_oper->basic_set, 0, 16);
491 memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10);
493 return pos + sizeof(struct ieee80211_ht_operation);
497 ecrnx_ie_build_vht_oper(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
498 u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
501 struct ieee80211_vht_operation *vht_oper;
502 /* Build HT Information */
503 *pos++ = WLAN_EID_VHT_OPERATION;
504 *pos++ = sizeof(struct ieee80211_vht_operation);
505 vht_oper = (struct ieee80211_vht_operation *)pos;
507 switch (ecrnx_vif->sta.ap->width) {
508 case NL80211_CHAN_WIDTH_80:
509 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; // Channel Width
511 ieee80211_frequency_to_channel(ecrnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0
512 CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.)
514 case NL80211_CHAN_WIDTH_160:
515 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; // Channel Width
517 ieee80211_frequency_to_channel(ecrnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0
518 CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.)
520 case NL80211_CHAN_WIDTH_80P80:
521 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; // Channel Width
523 ieee80211_frequency_to_channel(ecrnx_vif->sta.ap->center_freq1); // Channel Center Frequency Segment 0
525 ieee80211_frequency_to_channel(ecrnx_vif->sta.ap->center_freq2); // Channel Center Frequency Segment 1
528 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
534 vht_oper->basic_mcs_set = cpu_to_le16(ecrnx_hw->mod_params->mcs_map);
536 return pos + sizeof(struct ieee80211_vht_operation);
541 ecrnx_tdls_add_setup_start_ies(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
542 struct sk_buff *skb, const u8 *peer,
543 u8 action_code, bool initiator,
544 const u8 *extra_ies, size_t extra_ies_len)
546 enum nl80211_band band = ecrnx_vif->sta.ap->band;
547 struct ieee80211_supported_band *sband;
548 struct ieee80211_sta_ht_cap ht_cap;
549 struct ieee80211_sta_vht_cap vht_cap;
550 size_t offset = 0, noffset;
555 ecrnx_add_srates_ie(ecrnx_hw, skb);
556 ecrnx_add_ext_srates_ie(ecrnx_hw, skb);
557 ecrnx_tdls_add_supp_channels(ecrnx_hw, skb);
558 ecrnx_tdls_add_ext_capab(ecrnx_hw, skb);
560 /* add the QoS element if we support it */
561 if (/*local->hw.queues >= IEEE80211_NUM_ACS &&*/
562 action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
563 ecrnx_add_wmm_info_ie(skb, 0); /* no U-APSD */
565 ecrnx_tdls_add_oper_classes(ecrnx_vif, skb);
568 * with TDLS we can switch channels, and HT-caps are not necessarily
569 * the same on all bands. The specification limits the setup to a
570 * single HT-cap, so use the current band for now.
572 sband = ecrnx_hw->wiphy->bands[band];
573 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
574 if (((action_code == WLAN_TDLS_SETUP_REQUEST) ||
575 (action_code == WLAN_TDLS_SETUP_RESPONSE) ||
576 (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES)) &&
577 ht_cap.ht_supported /* (!sta || sta->sta.ht_cap.ht_supported)*/) {
578 ecrnx_ie_build_ht_cap(skb, &ht_cap, ht_cap.cap);
581 if (ht_cap.ht_supported &&
582 (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
583 ecrnx_tdls_add_bss_coex_ie(skb);
585 ecrnx_tdls_add_link_ie(ecrnx_hw, ecrnx_vif, skb, peer, initiator);
587 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
588 if (vht_cap.vht_supported) {
589 ecrnx_tdls_add_aid_ie(ecrnx_vif, skb);
590 ecrnx_ie_build_vht_cap(skb, &vht_cap, vht_cap.cap);
591 // Operating mode Notification (optional)
594 /* add any remaining IEs */
596 noffset = extra_ies_len;
597 pos = skb_put(skb, noffset - offset);
598 memcpy(pos, extra_ies + offset, noffset - offset);
606 ecrnx_tdls_add_setup_cfm_ies(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
607 struct sk_buff *skb, const u8 *peer, bool initiator,
608 const u8 *extra_ies, size_t extra_ies_len)
610 struct ieee80211_supported_band *sband;
611 enum nl80211_band band = ecrnx_vif->sta.ap->band;
612 struct ieee80211_sta_ht_cap ht_cap;
613 struct ieee80211_sta_vht_cap vht_cap;
615 size_t offset = 0, noffset;
616 struct ecrnx_sta *sta, *ap_sta;
621 sta = ecrnx_get_sta(ecrnx_hw, peer);
622 ap_sta = ecrnx_vif->sta.ap;
623 if (WARN_ON_ONCE(!sta || !ap_sta)) {
628 /* add the QoS param IE if both the peer and we support it */
630 ecrnx_add_wmm_param_ie(skb, ap_sta->acm, ap_sta->ac_param);
632 /* if HT support is only added in TDLS, we need an HT-operation IE */
633 sband = ecrnx_hw->wiphy->bands[band];
634 memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
635 if (ht_cap.ht_supported && !ap_sta->ht && sta->ht) {
636 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
637 /* send an empty HT operation IE */
638 ecrnx_ie_build_ht_oper(ecrnx_hw, ecrnx_vif, pos, &ht_cap, 0);
641 ecrnx_tdls_add_link_ie(ecrnx_hw, ecrnx_vif, skb, peer, initiator);
643 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
644 if (vht_cap.vht_supported && !ap_sta->vht && sta->vht) {
645 pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation));
646 ecrnx_ie_build_vht_oper(ecrnx_hw, ecrnx_vif, pos, &ht_cap, 0);
647 // Operating mode Notification (optional)
650 /* add any remaining IEs */
652 noffset = extra_ies_len;
653 pos = skb_put(skb, noffset - offset);
654 memcpy(pos, extra_ies + offset, noffset - offset);
661 ecrnx_tdls_add_ies(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
662 struct sk_buff *skb, const u8 *peer,
663 u8 action_code, u16 status_code,
664 bool initiator, const u8 *extra_ies,
665 size_t extra_ies_len, u8 oper_class,
666 struct cfg80211_chan_def *chandef)
668 switch (action_code) {
669 case WLAN_TDLS_SETUP_REQUEST:
670 case WLAN_TDLS_SETUP_RESPONSE:
671 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
672 if (status_code == 0)
673 ecrnx_tdls_add_setup_start_ies(ecrnx_hw, ecrnx_vif, skb, peer, action_code,
674 initiator, extra_ies, extra_ies_len);
676 case WLAN_TDLS_SETUP_CONFIRM:
677 if (status_code == 0)
678 ecrnx_tdls_add_setup_cfm_ies(ecrnx_hw, ecrnx_vif, skb, peer, initiator,
679 extra_ies, extra_ies_len);
682 case WLAN_TDLS_TEARDOWN:
683 case WLAN_TDLS_DISCOVERY_REQUEST:
685 memcpy(skb_put(skb, extra_ies_len), extra_ies,
687 if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
688 ecrnx_tdls_add_link_ie(ecrnx_hw, ecrnx_vif, skb, peer, initiator);
694 ecrnx_tdls_send_mgmt_packet_data(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
695 const u8 *peer, u8 action_code, u8 dialog_token,
696 u16 status_code, u32 peer_capability, bool initiator,
697 const u8 *extra_ies, size_t extra_ies_len, u8 oper_class,
698 struct cfg80211_chan_def *chandef)
702 struct ieee80211_supported_band *ecrnx_band_2GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
703 #ifdef CONFIG_ECRNX_5G
704 struct ieee80211_supported_band *ecrnx_band_5GHz = ecrnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
706 skb = netdev_alloc_skb(ecrnx_vif->ndev,
707 sizeof(struct ieee80211_tdls_data) + // ethhdr + TDLS info
708 10 + /* supported rates */
709 6 + /* extended supported rates */
710 #ifdef CONFIG_ECRNX_5G
711 (2 + ecrnx_band_2GHz->n_channels + ecrnx_band_5GHz->n_channels) + /* supported channels */
713 (2 + ecrnx_band_2GHz->n_channels) +
715 sizeof(struct ieee_types_extcap) +
716 sizeof(struct ieee80211_wmm_param_ie) +
717 4 + /* oper classes */
718 28 + //sizeof(struct ieee80211_ht_cap) +
719 sizeof(struct ieee_types_bss_co_2040) +
720 sizeof(struct ieee80211_tdls_lnkie) +
721 (2 + sizeof(struct ieee80211_vht_cap)) +
723 (2 + sizeof(struct ieee80211_ht_operation)) +
729 switch (action_code) {
730 case WLAN_TDLS_SETUP_REQUEST:
731 case WLAN_TDLS_SETUP_RESPONSE:
732 case WLAN_TDLS_SETUP_CONFIRM:
733 case WLAN_TDLS_TEARDOWN:
734 case WLAN_TDLS_DISCOVERY_REQUEST:
735 ret = ecrnx_tdls_prepare_encap_data(ecrnx_hw, ecrnx_vif, peer, action_code,
736 dialog_token, status_code, skb);
739 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
740 ret = ecrnx_prep_tdls_direct(ecrnx_hw, ecrnx_vif, peer, action_code,
741 dialog_token, status_code, skb);
752 ecrnx_tdls_add_ies(ecrnx_hw, ecrnx_vif, skb, peer, action_code, status_code,
753 initiator, extra_ies, extra_ies_len, oper_class, chandef);
755 if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
758 struct cfg80211_mgmt_tx_params params;
760 params.len = skb->len;
761 params.buf = skb->data;
762 ret = ecrnx_start_mgmt_xmit(ecrnx_vif, NULL, ¶ms, false, &cookie);
764 ret = ecrnx_start_mgmt_xmit(ecrnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie);
765 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
769 switch (action_code) {
770 case WLAN_TDLS_SETUP_REQUEST:
771 case WLAN_TDLS_SETUP_RESPONSE:
772 case WLAN_TDLS_SETUP_CONFIRM:
780 ret = ecrnx_select_txq(ecrnx_vif, skb);
781 ret = ecrnx_start_xmit(skb, ecrnx_vif->ndev);