📄 bcm43xx_xmit.c
字号:
u8 fallback_bitrate; int ofdm_modulation; int fallback_ofdm_modulation; u16 plcp_fragment_len = fragment_len; u16 flags = 0; u16 control = 0; u16 wsec_rate = 0; u16 encrypt_frame; /* Now construct the TX header. */ memset(txhdr, 0, sizeof(*txhdr)); bitrate = bcm->softmac->txrates.default_rate; ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); /* Set Frame Control from 80211 header. */ txhdr->frame_control = wireless_header->frame_ctl; /* Copy address1 from 80211 header. */ memcpy(txhdr->mac1, wireless_header->addr1, 6); /* Set the fallback duration ID. */ txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header, fallback_bitrate); /* Set the cookie (used as driver internal ID for the frame) */ txhdr->cookie = cpu_to_le16(cookie); /* Hardware appends FCS. */ plcp_fragment_len += IEEE80211_FCS_LEN; /* Hardware encryption. */ encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; if (encrypt_frame && !bcm->ieee->host_encrypt) { const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; memcpy(txhdr->wep_iv, hdr->payload, 4); /* Hardware appends ICV. */ plcp_fragment_len += 4; wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) & BCM43xx_TXHDR_WSEC_ALGO_MASK; wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; } /* Generate the PLCP header and the fallback PLCP header. */ bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), plcp_fragment_len, bitrate, ofdm_modulation); bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, fallback_bitrate, fallback_ofdm_modulation); /* Set the CONTROL field */ if (ofdm_modulation) control |= BCM43xx_TXHDRCTL_OFDM; if (bcm->short_preamble) //FIXME: could be the other way around, please test control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; /* Set the FLAGS field */ if (!is_multicast_ether_addr(wireless_header->addr1) && !is_broadcast_ether_addr(wireless_header->addr1)) flags |= BCM43xx_TXHDRFLAG_EXPECTACK; if (1 /* FIXME: PS poll?? */) flags |= 0x10; // FIXME: unknown meaning. if (fallback_ofdm_modulation) flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; if (is_first_fragment) flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; /* Set WSEC/RATE field */ wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT) & BCM43xx_TXHDR_RATE_MASK; /* Generate the RTS/CTS packet, if required. */ /* FIXME: We should first try with CTS-to-self, * if we are on 80211g. If we get too many * failures (hidden nodes), we should switch back to RTS/CTS. */ if (0/*FIXME txctl->use_rts_cts*/) { bcm43xx_generate_rts(phy, txhdr, &flags, 0/*FIXME txctl->rts_cts_rate*/, wireless_header); } txhdr->flags = cpu_to_le16(flags); txhdr->control = cpu_to_le16(control); txhdr->wsec_rate = cpu_to_le16(wsec_rate);}static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, int ofdm, int adjust_2053, int adjust_2050){ struct bcm43xx_radioinfo *radio = bcm->current_core->radio; struct bcm43xx_phyinfo *phy = bcm->current_core->phy; s32 tmp; switch (radio->version) { case 0x2050: if (ofdm) { tmp = in_rssi; if (tmp > 127) tmp -= 256; tmp *= 73; tmp /= 64; if (adjust_2050) tmp += 25; else tmp -= 3; } else { if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { if (in_rssi > 63) in_rssi = 63; tmp = radio->nrssi_lt[in_rssi]; tmp = 31 - tmp; tmp *= -131; tmp /= 128; tmp -= 57; } else { tmp = in_rssi; tmp = 31 - tmp; tmp *= -149; tmp /= 128; tmp -= 68; } if (phy->type == BCM43xx_PHYTYPE_G && adjust_2050) tmp += 25; } break; case 0x2060: if (in_rssi > 127) tmp = in_rssi - 256; else tmp = in_rssi; break; default: tmp = in_rssi; tmp -= 11; tmp *= 103; tmp /= 64; if (adjust_2053) tmp -= 109; else tmp -= 83; } return (s8)tmp;}static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi){ struct bcm43xx_phyinfo *phy = bcm->current_core->phy; s8 ret; if (phy->type == BCM43xx_PHYTYPE_A) { //TODO: Incomplete specs. ret = 0; } else ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); return ret;}int bcm43xx_rx(struct bcm43xx_private *bcm, struct sk_buff *skb, struct bcm43xx_rxhdr *rxhdr){ struct bcm43xx_plcp_hdr4 *plcp; struct ieee80211_rx_stats stats; struct ieee80211_hdr_4addr *wlhdr; u16 frame_ctl; int is_packet_for_us = 0; int err = -EINVAL; const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); /* Skip two unknown bytes and the PLCP header. */ skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); } else { plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); /* Skip the PLCP header. */ skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); } /* The SKB contains the PAYLOAD (wireless header + data) * at this point. The FCS at the end is stripped. */ memset(&stats, 0, sizeof(stats)); stats.mac_time = le16_to_cpu(rxhdr->mactime); stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); stats.signal = rxhdr->signal_quality; //FIXME//TODO stats.noise = if (is_ofdm) stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); else stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); stats.received_channel = bcm->current_core->radio->channel;//TODO stats.control = stats.mask = IEEE80211_STATMASK_SIGNAL |//TODO IEEE80211_STATMASK_NOISE | IEEE80211_STATMASK_RATE | IEEE80211_STATMASK_RSSI; if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) stats.freq = IEEE80211_52GHZ_BAND; else stats.freq = IEEE80211_24GHZ_BAND; stats.len = skb->len; bcm->stats.last_rx = jiffies; if (bcm->ieee->iw_mode == IW_MODE_MONITOR) { err = ieee80211_rx(bcm->ieee, skb, &stats); return (err == 0) ? -EINVAL : 0; } wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); switch (bcm->ieee->iw_mode) { case IW_MODE_ADHOC: if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || is_broadcast_ether_addr(wlhdr->addr1) || is_multicast_ether_addr(wlhdr->addr1) || bcm->net_dev->flags & IFF_PROMISC) is_packet_for_us = 1; break; case IW_MODE_INFRA: default: /* When receiving multicast or broadcast packets, filter out the packets we send ourself; we shouldn't see those */ if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && (is_broadcast_ether_addr(wlhdr->addr1) || is_multicast_ether_addr(wlhdr->addr1) || bcm->net_dev->flags & IFF_PROMISC))) is_packet_for_us = 1; break; } frame_ctl = le16_to_cpu(wlhdr->frame_ctl); if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { frame_ctl &= ~IEEE80211_FCTL_PROTECTED; wlhdr->frame_ctl = cpu_to_le16(frame_ctl); /* trim IV and ICV */ /* FIXME: this must be done only for WEP encrypted packets */ if (skb->len < 32) { dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " "set and length < 32)\n"); return -EINVAL; } else { memmove(skb->data + 4, skb->data, 24); skb_pull(skb, 4); skb_trim(skb, skb->len - 4); stats.len -= 8; } wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); } switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); break; case IEEE80211_FTYPE_DATA: if (is_packet_for_us) { err = ieee80211_rx(bcm->ieee, skb, &stats); err = (err == 0) ? -EINVAL : 0; } break; case IEEE80211_FTYPE_CTL: break; default: assert(0); return -EINVAL; } return err;}/* vim: set ts=8 sw=8 sts=8: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -