/* WMI command API */ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, WMI_CMD_ID cmd_id) { A_STATUS status; struct cookie *cookie; if (wbuf_push(buf, sizeof(WMI_CMD_HDR)) == NULL) { return -ENOMEM; } WMI_SET_FIELD(wbuf_header(buf), WMI_CMD_HDR, COMMANDID, cmd_id); //WMI_CMD_HDR_SET_DEVID(cmd_hdr, 0); // unused cookie = ol_alloc_cookie(wmi_handle); if (!cookie) { return -ENOMEM; } cookie->PacketContext = buf; SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, cookie, wbuf_header(buf), len+sizeof(WMI_CMD_HDR), /* htt_host_data_dl_len(buf)+20 */ wmi_handle->wmi_endpoint_id, 0/*htc_tag*/); SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, buf); status = HTCSendPkt(wmi_handle->htc_handle, &cookie->HtcPkt); return ((status == A_OK) ? EOK : -1); }
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; }
/* * Add privacy headers appropriate for the specified key. */ static int ccmp_encap(struct ieee80211_key *k, wbuf_t wbuf, u_int8_t keyid) { struct ccmp_ctx *ctx = k->wk_private; struct ieee80211com *ic = ctx->cc_ic; u_int8_t *ivp; int hdrlen; int is4addr, isqos, owl_wdswar; struct ieee80211_frame *wh; struct ieee80211_node *ni = wbuf_get_node(wbuf); wh = (struct ieee80211_frame *)wbuf_header(wbuf); is4addr = ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) ? 1 : 0; isqos = IEEE80211_QOS_HAS_SEQ(wh); owl_wdswar = (ni->ni_flags & IEEE80211_NODE_OWL_WDSWAR); hdrlen = ieee80211_hdrspace(ic, wbuf_header(wbuf)); /* * Copy down 802.11 header and add the IV, KeyID, and ExtIV. */ #ifndef __CARRIER_PLATFORM__ ivp = (u_int8_t *)wbuf_push(wbuf, ccmp.ic_header); /* * refresh the wh pointer, * wbuf header pointer is changed with wbuf_push. */ wh = (struct ieee80211_frame *) wbuf_header(wbuf); /* recompute wh */ memmove(ivp, ivp + ccmp.ic_header, hdrlen); #else if (wbuf_is_encap_done(wbuf)) { ivp = (u_int8_t *)wbuf_header(wbuf); } else { ivp = (u_int8_t *)wbuf_push(wbuf, ccmp.ic_header); memmove(ivp, ivp + ccmp.ic_header, hdrlen); /* * refresh the wh pointer, * wbuf header pointer is changed with wbuf_push. */ wh = (struct ieee80211_frame *) wbuf_header(wbuf); /* recompute wh */ } #endif ivp += hdrlen; /* * Due to OWL specific HW bug, increment key tsc by 16, since * we're copying the TID into bits [3:0] of IV0. * XXX: Need logic to not implement workaround for SOWL or greater. */ if (is4addr && isqos && owl_wdswar) k->wk_keytsc += 16; else k->wk_keytsc++; /* XXX wrap at 48 bits */ ivp[0] = k->wk_keytsc >> 0; /* PN0 */ ivp[1] = k->wk_keytsc >> 8; /* PN1 */ ivp[2] = 0; /* Reserved */ ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ ivp[4] = k->wk_keytsc >> 16; /* PN2 */ ivp[5] = k->wk_keytsc >> 24; /* PN3 */ ivp[6] = k->wk_keytsc >> 32; /* PN4 */ ivp[7] = k->wk_keytsc >> 40; /* PN5 */ /* * Finally, do software encrypt if neeed. */ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { if (!ccmp_encrypt(k, wbuf, hdrlen, 0)) { return 0; } } if ((k->wk_flags & IEEE80211_KEY_MFP) && IEEE80211_IS_MFP_FRAME(wh)) { if (ic->ic_get_mfpsupport(ic) != IEEE80211_MFP_HW_CRYPTO) { /* HW MFP is not enabled - do software encrypt */ if (!ccmp_encrypt(k, wbuf, hdrlen, 1)) { return 0; } } } return 1; }
static int ath_rx_assemble_buf(struct ath_softc *sc, wbuf_t *wbuf, ieee80211_rx_status_t *status, u_int16_t keyix) { struct ath_buf *bf = NULL; struct sk_buff *kb = NULL; wbuf_t nwbuf; if (wbuf_next(*wbuf)) { /* for linux multiple receive buffer */ bf = ATH_GET_RX_CONTEXT_BUF(wbuf_next(*wbuf)); bf->bf_mpdu = wbuf_next(*wbuf); /* unlink the top half buffer and bottom half buffer */ wbuf_setnextpkt(*wbuf, NULL); /* use skb_copy_expand for combining two buffer, nwbuf = wbuf##twbuf */ nwbuf = skb_copy_expand((struct sk_buff *)*wbuf, 0, wbuf_get_pktlen(*wbuf)+wbuf_get_pktlen(bf->bf_mpdu), GFP_ATOMIC); if (nwbuf != NULL) { skb_copy_bits(bf->bf_mpdu, 0, wbuf_header(nwbuf) + wbuf_get_pktlen(*wbuf), wbuf_get_pktlen(bf->bf_mpdu)); kb = (struct sk_buff *)nwbuf; ((struct ieee80211_cb *)kb->cb)->context = &(((struct ieee80211_cb *)kb->cb)[1]); skb_put(nwbuf,wbuf_get_pktlen(bf->bf_mpdu)); wbuf_free(bf->bf_mpdu); bf->bf_mpdu = nwbuf; ATH_SET_RX_CONTEXT_BUF(nwbuf, bf); } else { ATH_GET_RX_CONTEXT_BUF(*wbuf)->bf_status |= ATH_BUFSTATUS_FREE; if (sc->sc_enhanceddmasupport) { wbuf_push(*wbuf, sc->sc_rxstatuslen); wbuf_push(bf->bf_mpdu, sc->sc_rxstatuslen); } wbuf_trim(bf->bf_mpdu, wbuf_get_pktlen(bf->bf_mpdu)); wbuf_trim(*wbuf, wbuf_get_pktlen(*wbuf)); bf->bf_buf_addr[0] = wbuf_map_single(sc->sc_osdev, bf->bf_mpdu, BUS_DMA_FROMDEVICE, OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext)); /* relink unused wbuf to H/W */ ath_rx_requeue(sc, *wbuf); ath_rx_requeue(sc, bf->bf_mpdu); return -1; } ATH_GET_RX_CONTEXT_BUF(*wbuf)->bf_status |= ATH_BUFSTATUS_FREE; if (sc->sc_enhanceddmasupport) { wbuf_push(*wbuf, sc->sc_rxstatuslen); } wbuf_trim(*wbuf, wbuf_get_pktlen(*wbuf)); /* relink unused wbuf to H/W */ ath_rx_requeue(sc, *wbuf); *wbuf = bf->bf_mpdu; } return 0; }
int32_t ieee80211_send_aow_ctrl_ipformat(struct ieee80211_node* ni, void* pkt, u_int32_t len, u_int32_t seqno, u_int64_t tsf, u_int32_t audio_channel, bool setlogSync) { struct ieee80211com *ic = aowinfo.ic; struct ieee80211vap *vap = ni->ni_vap; wbuf_t wbuf; struct ether_header *eh; char* pdata = NULL; struct audio_pkt* apkt = NULL; int i = 0; u_int32_t offset; int32_t retVal; u_int32_t total_len; u_int8_t* frame; total_len = sizeof(struct audio_pkt) + len + ATH_QOS_FIELD_SIZE; wbuf = ieee80211_get_aow_frame(ni, &frame, total_len); if (wbuf == NULL) { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); return -ENOMEM; } offset = ATH_QOS_FIELD_SIZE + sizeof(struct audio_pkt); /* prepare the ethernet header */ wbuf_push(wbuf, sizeof(struct ether_header)); eh = (struct ether_header*)wbuf_header(wbuf); /* prepare te ether header */ IEEE80211_ADDR_COPY(eh->ether_dhost, ni->ni_macaddr); IEEE80211_ADDR_COPY(eh->ether_shost, vap->iv_myaddr); eh->ether_type = ETHERTYPE_IP; pdata = (char*)&eh[1]; apkt = (struct audio_pkt*)pdata; apkt->signature = ATH_AOW_SIGNATURE; apkt->seqno = seqno; apkt->timestamp = tsf; apkt->pkt_len = len; apkt->pkt_type = AOW_CTRL_PKT; apkt->params |= (setlogSync & ATH_AOW_PARAMS_LOGSYNC_FLG_MASK)<< ATH_AOW_PARAMS_LOGSYNC_FLG_S; apkt->audio_channel = audio_channel; /* update the volume info */ for (i = 0; i < AOW_MAX_AUDIO_CHANNELS; i++) { OS_MEMCPY(apkt->volume_info.ch[i].info, ic->ic_aow.volume_info.ch[i].info, AOW_VOLUME_DATA_LENGTH); } memcpy((pdata + offset), pkt, len); retVal = ath_tx_send((wbuf_t)wbuf); ieee80211_free_node(ni); return retVal; }