Esempio n. 1
0
/* 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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/*
 * 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;
}
Esempio n. 4
0
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;

}
Esempio n. 5
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;


}