wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, int len) { wmi_buf_t wmi_buf; /* NOTE: For now the wbuf type is used as WBUF_TX_CTL * But this need to be changed appropriately to reserve * proper headroom for wmi_buffers */ wmi_buf = wbuf_alloc(wmi_handle->osdev, WBUF_TX_CTL, len); if( NULL == wmi_buf ) { /* wbuf_alloc returns NULL if the internel pool in wmi_handle->osdev * is empty */ return NULL; } /* Clear the wmi buffer */ OS_MEMZERO(wbuf_header(wmi_buf), len); /* * Set the length of the buffer to match the allocation size. */ wbuf_set_pktlen(wmi_buf, len); return wmi_buf; }
/* TODO: only support linux for now */ void wlan_offchan_send_data_frame(struct ieee80211_node *ni, struct net_device *netdev) { #if defined(LINUX) || defined(__linux__) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; wbuf_t wbuf; struct ieee80211_qosframe *qwh; const u_int8_t dst[6] = {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}; struct sk_buff *skb; wbuf = wbuf_alloc(ic->ic_osdev, WBUF_TX_DATA, 1000); if (wbuf == NULL) { return ; } ieee80211_prepare_qosnulldata(ni, wbuf, WME_AC_VO); qwh = (struct ieee80211_qosframe *)wbuf_header(wbuf); ieee80211_send_setup(vap, ni, (struct ieee80211_frame *)qwh, IEEE80211_FC0_TYPE_DATA, vap->iv_myaddr, /* SA */ dst, /* DA */ ni->ni_bssid); wbuf_set_pktlen(wbuf, 1000); /* force with NONPAUSE_TID */ wbuf_set_tid(wbuf, OFFCHAN_EXT_TID_NONPAUSE); skb = (struct sk_buff *)wbuf; skb->dev = netdev; dev_queue_xmit(skb); #endif }
wbuf_t ath_net80211_uapsd_allocqosnullframe(ieee80211_handle_t ieee) { wbuf_t wbuf; struct ieee80211com *ic = NET80211_HANDLE(ieee); wbuf = wbuf_alloc(ic->ic_osdev, WBUF_TX_MGMT, sizeof(struct ieee80211_qosframe)); if (wbuf != NULL) wbuf_push(wbuf, sizeof(struct ieee80211_qosframe)); return wbuf; }
/*zhaoyang1 add start for interfere ap*/ wbuf_t autelan_beacon_alloc(struct ieee80211_node *ni, struct ieee80211_beacon_offsets *bo, u_int8_t *ap_mac, u_int8_t chan) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; wbuf_t wbuf; struct ieee80211_frame *wh; u_int8_t *frm; wbuf = wbuf_alloc(ic->ic_osdev, WBUF_TX_BEACON, MAX_TX_RX_PACKET_SIZE); if (wbuf == NULL) return NULL; wh = (struct ieee80211_frame *)wbuf_header(wbuf); wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(u_int16_t *)wh->i_dur = 0; IEEE80211_ADDR_COPY(wh->i_addr1, IEEE80211_GET_BCAST_ADDR(ic)); IEEE80211_ADDR_COPY(wh->i_addr2, ap_mac); IEEE80211_ADDR_COPY(wh->i_addr3, ap_mac); *(u_int16_t *)wh->i_seq = 0; frm = (u_int8_t *)&wh[1]; frm = autelan_beacon_init(ni, bo, frm, chan); if (ieee80211_vap_copy_beacon_is_set(vap)) { store_beacon_frame(vap, (u_int8_t *)wh, (frm - (u_int8_t *)wh)); } wbuf_set_pktlen(wbuf, (frm - (u_int8_t *) wbuf_header(wbuf))); wbuf_set_node(wbuf, ieee80211_ref_node(ni)); IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MLME, vap->iv_myaddr, "%s \n", __func__); return wbuf; }
/* * Send a probe response frame. * NB: for probe response, the node may not represent the peer STA. * We could use BSS node to reduce the memory usage from temporary node. */ int ieee80211_send_proberesp(struct ieee80211_node *ni, u_int8_t *macaddr, const void *optie, const size_t optielen) { struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ieee80211_rsnparms *rsn = &vap->iv_rsn; wbuf_t wbuf; struct ieee80211_frame *wh; u_int8_t *frm; u_int16_t capinfo; int enable_htrates; bool add_wpa_ie = true; ASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_BTAMP); wbuf = wbuf_alloc(ic->ic_osdev, WBUF_TX_MGMT, MAX_TX_RX_PACKET_SIZE); if (wbuf == NULL) return -ENOMEM; #ifdef IEEE80211_DEBUG_REFCNT printk("%s ,line %u: increase node %p <%s> refcnt to %d\n", __func__, __LINE__, ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)); #endif /* setup the wireless header */ wh = (struct ieee80211_frame *)wbuf_header(wbuf); ieee80211_send_setup(vap, ni, wh, IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP, vap->iv_myaddr, macaddr, ieee80211_node_get_bssid(ni)); frm = (u_int8_t *)&wh[1]; /* * probe response frame format * [8] time stamp * [2] beacon interval * [2] cabability information * [tlv] ssid * [tlv] supported rates * [tlv] parameter set (FH/DS) * [tlv] parameter set (IBSS) * [tlv] extended rate phy (ERP) * [tlv] extended supported rates * [tlv] country (if present) * [3] power constraint * [tlv] WPA * [tlv] WME * [tlv] HT Capabilities * [tlv] HT Information * [tlv] Atheros Advanced Capabilities */ OS_MEMZERO(frm, 8); /* timestamp should be filled later */ frm += 8; *(u_int16_t *)frm = htole16(vap->iv_bss->ni_intval); frm += 2; if (vap->iv_opmode == IEEE80211_M_IBSS) capinfo = IEEE80211_CAPINFO_IBSS; else capinfo = IEEE80211_CAPINFO_ESS; if (IEEE80211_VAP_IS_PRIVACY_ENABLED(vap)) capinfo |= IEEE80211_CAPINFO_PRIVACY; if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; if (ic->ic_flags & IEEE80211_F_SHSLOT) capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; if (ieee80211_ic_doth_is_set(ic) && ieee80211_vap_doth_is_set(vap)) capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT; *(u_int16_t *)frm = htole16(capinfo); frm += 2; frm = ieee80211_add_ssid(frm, vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen); frm = ieee80211_add_rates(frm, &vap->iv_bss->ni_rates, ic); if (!IEEE80211_IS_CHAN_FHSS(vap->iv_bsschan)) { *frm++ = IEEE80211_ELEMID_DSPARMS; *frm++ = 1; *frm++ = ieee80211_chan2ieee(ic, ic->ic_curchan); } if (vap->iv_opmode == IEEE80211_M_IBSS) { *frm++ = IEEE80211_ELEMID_IBSSPARMS; *frm++ = 2; *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ } if (IEEE80211_IS_COUNTRYIE_ENABLED(ic)) { frm = ieee80211_add_country(frm, vap); } if (ieee80211_ic_doth_is_set(ic) && ieee80211_vap_doth_is_set(vap)) { *frm++ = IEEE80211_ELEMID_PWRCNSTR; *frm++ = 1; *frm++ = IEEE80211_PWRCONSTRAINT_VAL(vap); } #if ATH_SUPPORT_IBSS_DFS if (vap->iv_opmode == IEEE80211_M_IBSS) { frm = ieee80211_add_ibss_dfs(frm,vap); } #endif if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) || IEEE80211_IS_CHAN_11NG(ic->ic_curchan)) { frm = ieee80211_add_erp(frm, ic); } /* * check if os shim has setup RSN IE it self. */ IEEE80211_VAP_LOCK(vap); if (vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].length) { add_wpa_ie = ieee80211_check_wpaie(vap, vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].ie, vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].length); } if (vap->iv_opt_ie.length) { add_wpa_ie = ieee80211_check_wpaie(vap, vap->iv_opt_ie.ie, vap->iv_opt_ie.length); } IEEE80211_VAP_UNLOCK(vap); if (add_wpa_ie) { if (RSN_AUTH_IS_RSNA(rsn)) frm = ieee80211_setup_rsn_ie(vap, frm); } #if ATH_SUPPORT_WAPI if (RSN_AUTH_IS_WAI(rsn)) frm = ieee80211_setup_wapi_ie(vap, frm); #endif frm = ieee80211_add_xrates(frm, &vap->iv_bss->ni_rates, ic); enable_htrates = ieee80211vap_htallowed(vap); if (IEEE80211_IS_CHAN_11N(ic->ic_curchan) && enable_htrates) { frm = ieee80211_add_htcap(frm, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP); if (!IEEE80211_IS_HTVIE_ENABLED(ic)) frm = ieee80211_add_htcap_pre_ana(frm, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP); frm = ieee80211_add_htinfo(frm, ni); if (!IEEE80211_IS_HTVIE_ENABLED(ic)) frm = ieee80211_add_htinfo_pre_ana(frm, ni); if (!(ic->ic_flags & IEEE80211_F_COEXT_DISABLE)) { frm = ieee80211_add_obss_scan(frm, ni); frm = ieee80211_add_extcap(frm, ni); } } if (add_wpa_ie) { if (RSN_AUTH_IS_WPA(rsn)) frm = ieee80211_setup_wpa_ie(vap, frm); } if (ieee80211_vap_wme_is_set(vap) && (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_BTAMP)) /* don't support WMM in ad-hoc for now */ frm = ieee80211_add_wme_param(frm, &ic->ic_wme, IEEE80211_VAP_IS_UAPSD_ENABLED(vap)); if ((IEEE80211_IS_CHAN_11N(ic->ic_curchan)) && (IEEE80211_IS_HTVIE_ENABLED(ic)) && enable_htrates) { frm = ieee80211_add_htcap_vendor_specific(frm, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP); frm = ieee80211_add_htinfo_vendor_specific(frm, ni); } if (vap->iv_bss->ni_ath_flags) { frm = ieee80211_add_athAdvCap(frm, vap->iv_bss->ni_ath_flags, vap->iv_bss->ni_ath_defkeyindex); } else { frm = ieee80211_add_athAdvCap(frm, 0, IEEE80211_INVAL_DEFKEY); } /* Insert ieee80211_ie_ath_extcap IE to beacon */ if (ic->ic_ath_extcap) frm = ieee80211_add_athextcap(frm, ic->ic_ath_extcap, ic->ic_weptkipaggr_rxdelim); #ifdef notyet if (ni->ni_ath_ie != NULL) /* XXX */ frm = ieee80211_add_ath(frm, ni); #endif IEEE80211_VAP_LOCK(vap); if (vap->iv_opt_ie.length) { OS_MEMCPY(frm, vap->iv_opt_ie.ie, vap->iv_opt_ie.length); frm += vap->iv_opt_ie.length; } if (vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].length) { OS_MEMCPY(frm, vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].ie, vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].length); frm += vap->iv_app_ie[IEEE80211_FRAME_TYPE_PROBERESP].length; } /* Add the Application IE's */ frm = ieee80211_mlme_app_ie_append(vap, IEEE80211_FRAME_TYPE_PROBERESP, frm); IEEE80211_VAP_UNLOCK(vap); if (optie != NULL && optielen != 0) { OS_MEMCPY(frm, optie, optielen); frm += optielen; } wbuf_set_pktlen(wbuf, (frm - (u_int8_t *)wbuf_header(wbuf))); return ieee80211_send_mgmt(vap,ni, wbuf,true); }
/* * Start continuous transmit operation. */ static int tx99_start(struct ath_softc *sc) { static struct ath_tx99_tgt tx99_tgt; struct ath_tx99 *tx99 = sc->sc_tx99; struct ath_hal *ah = sc->sc_ah; int is2GHz = 0; wbuf_t wbuf; HAL_CHANNEL *chan = NULL; if(tx99->recv) { ath_hal_phydisable(ah); DPRINTF(sc, ATH_DEBUG_TX99, "%s: tx99 continuous receive mode, return!\n", __func__); return 0; } /* check tx99 running state */ if(tx99->tx99_state){ /* already active */ DPRINTF(sc, ATH_DEBUG_TX99, "%s: already running, return!\n", __func__); return 0; } OS_DELAY(10000); /* set tx99 state active */ tx99->tx99_state = 1; /* allocate diag packet buffer */ if (tx99->wbuf == NULL) { tx99->wbuf = wbuf_alloc(sc->sc_osdev, WBUF_TX_DATA, 2000); if (tx99->wbuf == NULL) { DPRINTF(sc, ATH_DEBUG_TX99, "%s: unable to allocate wbuf!\n", __func__); tx99->tx99_state = 0; return -ENOMEM; } } else { DPRINTF(sc, ATH_DEBUG_TX99, "%s: wbuf was allocated before!\n", __func__); } wbuf = tx99->wbuf; /* drain all tx queue */ ath_drain_txq(sc); /* * Setup channel using configured frequency+flags. */ if (tx99_channel_setup(sc)) { DPRINTF(sc, ATH_DEBUG_TX99, "%s: unable to setup channel!\n", __func__); /* recover the default channel and mode */ tx99->txfreq = 2412;/* ieee channel frequecy */ tx99->htmode = 0; tx99->htext = 0; goto bad; } /* * Setup tx power limit */ chan = &sc->sc_curchan; is2GHz = TX99_IS_CHAN_2GHZ(chan); ath_hal_settxpowlimit(ah,tx99->txpower,0,is2GHz); /* set tx99 enable */ tx99_tgt.txrate = htonl(tx99->txrate); tx99_tgt.txrc = htonl(tx99->txrc); tx99_tgt.txpower = htonl(tx99->txpower); tx99_tgt.txchain = htonl(tx99->chanmask); tx99_tgt.htmode = htonl(tx99->htmode); tx99_tgt.type = htonl(tx99->type); tx99_tgt.chtype = htonl(TX99_IS_CHAN_5GHZ(chan)); tx99_tgt.txantenna = htonl(0); if( tx99->txpower < 60 ) /* only update channel pwr if not default MAX power */ ath_hal_tx99_channel_pwr_update(ah, chan, tx99->txpower); #ifdef ATH_SUPPORT_HTC ah_tx99_start(ah, (u_int8_t *)&tx99_tgt); /* send diag packet */ { struct ath_txep *txep; A_STATUS ret; adf_nbuf_put_tail(skb, 1500); txep = sc->sc_ac2ep[WME_AC_VO]; /* send packet to target */ ret = HTCSendPkt(sc->sc_host_htc_handle, NULL ,skb, sc->sc_data_VO_ep); if(ret) { DPRINTF(sc, ATH_DEBUG_TX99, "%s: tx99 fail!\n", __func__); tx99_stop(sc, 0); } } #else if (ath_tx99_tgt_start(sc, tx99_tgt.chtype) != EOK) { goto bad; } #endif /* wait a while to make sure target setting ready */ OS_DELAY(50000); DPRINTF(sc, ATH_DEBUG_TX99, "%s: continuous transmit started!\n", __func__); return 0; bad: tx99_stop(sc, 0); return -EIO; }