u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum nl80211_iftype type) { __le16 fc = hdr->frame_control; /* drop ACK/CTS frames and incorrect hdr len (ctrl) */ if (len < 16) return NULL; if (ieee80211_is_data(fc)) { if (len < 24) /* drop incorrect hdr len (data) */ return NULL; if (ieee80211_has_a4(fc)) return NULL; if (ieee80211_has_tods(fc)) return hdr->addr1; if (ieee80211_has_fromds(fc)) return hdr->addr2; return hdr->addr3; } if (ieee80211_is_mgmt(fc)) { if (len < 24) /* drop incorrect hdr len (mgmt) */ return NULL; return hdr->addr3; } if (ieee80211_is_ctl(fc)) { if(ieee80211_is_pspoll(fc)) return hdr->addr1; if (ieee80211_is_back_req(fc)) { switch (type) { case NL80211_IFTYPE_STATION: return hdr->addr2; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: return hdr->addr1; default: break; /* fall through to the return */ } } } return NULL; }
static bool rtl_phydm_query_phy_status(struct rtl_priv *rtlpriv, u8 *phystrpt, struct ieee80211_hdr *hdr, struct rtl_stats *pstatus) { /* NOTE: phystrpt may be NULL, and need to fill default value */ struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv); struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); struct rtl_mac *mac = rtl_mac(rtlpriv); struct dm_per_pkt_info pktinfo; /* input of pydm */ struct dm_phy_status_info phy_info; /* output of phydm */ __le16 fc = hdr->frame_control; /* fill driver pstatus */ ether_addr_copy(pstatus->psaddr, ieee80211_get_SA(hdr)); /* fill pktinfo */ memset(&pktinfo, 0, sizeof(pktinfo)); pktinfo.data_rate = pstatus->rate; if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION) { pktinfo.station_id = 0; } else { /* TODO: use rtl_find_sta() to find ID */ pktinfo.station_id = 0xFF; } pktinfo.is_packet_match_bssid = (!ieee80211_is_ctl(fc) && (ether_addr_equal(mac->bssid, ieee80211_has_tods(fc) ? hdr->addr1 : ieee80211_has_fromds(fc) ? hdr->addr2 : hdr->addr3)) && (!pstatus->hwerror) && (!pstatus->crc) && (!pstatus->icv)); pktinfo.is_packet_to_self = pktinfo.is_packet_match_bssid && (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr)); pktinfo.is_to_self = (!pstatus->icv) && (!pstatus->crc) && (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr)); pktinfo.is_packet_beacon = (ieee80211_is_beacon(fc) ? true : false); /* query phy status */ if (phystrpt) odm_phy_status_query(dm, &phy_info, phystrpt, &pktinfo); else memset(&phy_info, 0, sizeof(phy_info)); /* copy phy_info from phydm to driver */ pstatus->rx_pwdb_all = phy_info.rx_pwdb_all; pstatus->bt_rx_rssi_percentage = phy_info.bt_rx_rssi_percentage; pstatus->recvsignalpower = phy_info.recv_signal_power; pstatus->signalquality = phy_info.signal_quality; pstatus->rx_mimo_signalquality[0] = phy_info.rx_mimo_signal_quality[0]; pstatus->rx_mimo_signalquality[1] = phy_info.rx_mimo_signal_quality[1]; pstatus->rx_packet_bw = phy_info.band_width; /* HT_CHANNEL_WIDTH_20 <- ODM_BW20M */ /* fill driver pstatus */ pstatus->packet_matchbssid = pktinfo.is_packet_match_bssid; pstatus->packet_toself = pktinfo.is_packet_to_self; pstatus->packet_beacon = pktinfo.is_packet_beacon; return true; }