Enscript Output

extractedLnx/linux-2.6.36/drivers/staging/otus/80211core/cinit.c_zfTxGenWlanHeader.c

u16_t zfTxGenWlanHeader(zdev_t* dev, zbuf_t* buf, u16_t* header, u16_t seq,
                        u8_t flag, u16_t plusLen, u16_t minusLen, u16_t port,
                        u16_t* da, u16_t* sa, u8_t up, u16_t *micLen,
                        u16_t* snap, u16_t snapLen, struct aggControl *aggControl)
{

    u16_t len;
    u16_t macCtrl;
    u32_t phyCtrl;
    u16_t hlen = 16;
    u16_t icvLen = 0;
    u16_t wdsPortId;
    u16_t vap = 0;
    u16_t mcs = 0;
    u16_t mt = 0;
    u8_t  qosType;
    u8_t  b1, b2;
    u16_t wdsPort;
    u8_t  encExemptionActionType;
    u16_t rateProbingFlag = 0;
    u8_t  tkipFrameOffset = 0;

#ifdef ZM_ENABLE_IBSS_WPA2PSK
    u8_t    res, peerIdx;
    u8_t    userIdx=0;
    u16_t   *iv16;
    u32_t   *iv32;
#endif

    zmw_get_wlan_dev(dev);

   /* Generate WLAN header */
    /* Frame control */
    header[4] = 0x0008 | (flag<<8);
    /* Duration */
    header[5] = 0x0000;

    if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
    {
        /* ToDS bit */
        header[4] |= 0x0100;

        /*Sometimes we wake up to tx/rx but AP still think we are sleeping, so still need to set this bit*/
        if ( zfPowerSavingMgrIsSleeping(dev) || wd->sta.psMgr.tempWakeUp == 1 )
        {
            header[4] |= 0x1000;
        }

        /* Address 1 = BSSID */
        header[6] = wd->sta.bssid[0];
        header[7] = wd->sta.bssid[1];
        header[8] = wd->sta.bssid[2];
        /* Address 3 = DA */
        header[12] = da[0];
        header[13] = da[1];
        header[14] = da[2];
    }
    else if (wd->wlanMode == ZM_MODE_PSEUDO)
    {
        /* Address 1 = DA */
        header[6] = da[0];
        header[7] = da[1];
        header[8] = da[2];
        /* Address 3 = 00:00:00:00:00:00 */
        header[12] = 0;
        header[13] = 0;
        header[14] = 0;

        /* PSEUDO test : WDS */
        if (wd->enableWDS)
        {
            /* ToDS and FromDS bit */
            header[4] |= 0x0300;

            /* Address 4 = SA */
            header[16] = 0;
            header[17] = 0;
            header[18] = 0;

            hlen = 19;
        }
    }
    else if (wd->wlanMode == ZM_MODE_IBSS)
    {
        /* Address 1 = DA */
        header[6] = da[0];
        header[7] = da[1];
        header[8] = da[2];
        /* Address 3 = BSSID */
        header[12] = wd->sta.bssid[0];
        header[13] = wd->sta.bssid[1];
        header[14] = wd->sta.bssid[2];

#ifdef ZM_ENABLE_IBSS_WPA2PSK
        zmw_enter_critical_section(dev);
        res = zfStaFindOppositeByMACAddr(dev, da, &peerIdx);
        if(res == 0) // Find opposite in our OppositeInfo Structure !
        {
            userIdx = peerIdx;
        }
        zmw_leave_critical_section(dev);
#endif
    }
    else if (wd->wlanMode == ZM_MODE_AP)
    {
        if (port < 0x20)
        /* AP mode */
        {
            /* FromDS bit */
            header[4] |= 0x0200;

            /* Address 1 = DA */
            header[6] = da[0];
            header[7] = da[1];
            header[8] = da[2];
            /* Address 3 = SA */
            header[12] = sa[0];
            header[13] = sa[1];
            header[14] = sa[2];

            if (port < ZM_MAX_AP_SUPPORT)
            {
                vap = port;
                header[14] += (vap<<8);
            }
        }
        else
        /* WDS port */
        {
            /* ToDS and FromDS bit */
            header[4] |= 0x0300;

            wdsPortId = port - 0x20;

            /* Address 1 = RA */
            header[6] = wd->ap.wds.macAddr[wdsPortId][0];
            header[7] = wd->ap.wds.macAddr[wdsPortId][1];
            header[8] = wd->ap.wds.macAddr[wdsPortId][2];
            /* Address 3 = DA */
            header[12] = da[0];
            header[13] = da[1];
            header[14] = da[2];
            /* Address 4 = SA */
            header[16] = sa[0];
            header[17] = sa[1];
            header[18] = sa[2];

            hlen = 19;
        }
    } /* else if (wd->wlanMode == ZM_MODE_AP) */

    /* Address 2 = TA */
    header[9] = wd->macAddr[0];
    header[10] = wd->macAddr[1];
#ifdef ZM_VAPMODE_MULTILE_SSID
    header[11] = wd->macAddr[2]; //Multiple SSID
#else
    header[11] = wd->macAddr[2] + (vap<<8); //VAP
#endif

    if ( (wd->wlanMode == ZM_MODE_IBSS) && (wd->XLinkMode) )
    {
        header[9]  = sa[0];
        header[10] = sa[1];
        header[11] = sa[2];
    }

    /* Sequence Control */
    header[15] = seq;


    if (wd->wlanMode == ZM_MODE_AP)
    {
        zfApGetStaTxRateAndQosType(dev, da, &phyCtrl, &qosType, &rateProbingFlag);
        mt = (u16_t)(phyCtrl & 0x3);
        mcs = (u16_t)((phyCtrl >> 16) & 0x3f);
#if 1
        //zfApGetStaQosType(dev, da, &qosType);

        /* if DA == WME STA */
        if (qosType == 1)
        {
            /* QoS data */
            header[4] |= 0x0080;

            /* QoS Control */
            header[hlen] = up;
            hlen += 1;
        }
#endif
    }

#if 0
    //AGG Test Code
    if (header[6] == 0x8000)
    {
        /* QoS data */
        header[4] |= 0x0080;

        /* QoS Control */
        header[hlen] = 0;
        hlen += 1;
    }
#endif

    if (wd->wlanMode == ZM_MODE_AP) {
        /* Todo: rate control here for qos field */
    }
    else {
        /* Rate control */
        zfStaGetTxRate(dev, da, &phyCtrl, &rateProbingFlag);
        mt = (u16_t)(phyCtrl & 0x3);
        mcs = (u16_t)((phyCtrl >> 16) & 0x3f);
    }

    if (wd->txMCS != 0xff)
    {
        /* fixed rate */
	    phyCtrl = ((u32_t)wd->txMCS<<16) + wd->txMT;
        mcs = wd->txMCS;
        mt = wd->txMT;
    }

    if (wd->enableAggregation)
    {
        /* force enable aggregation */
        if (wd->enableAggregation==2 && !(header[6]&0x1))
        {
            /* QoS data */
            header[4] |= 0x0080;

            /* QoS Control */
            header[hlen] = 0;
            hlen += 1;
        }
        /* if wd->enableAggregation=1 => force disable */
        /* if wd->enableAggregation=0 => auto */
    }

#ifdef ZM_ENABLE_AGGREGATION
    /*
     * aggregation control
     */

    /*
     * QoS data
     */
    if (wd->wlanMode == ZM_MODE_AP) {
        if (aggControl && mt == 2) {
            if (wd->enableAggregation==0 && !(header[6]&0x1))
            {
                header[4] |= 0x0080;

                /*
                 * QoS Control
                 */
                header[hlen] = 0;
                hlen += 1;
            }
        }
    }
#endif

    // MSDU Length
    len = zfwBufGetSize(dev, buf);

    /* Generate control setting */
    /* Backoff, Non-Burst and hardware duration */
    macCtrl = 0x208;

    /* ACK */
    if ((header[6] & 0x1) == 0x1)
    {
        /* multicast frame : Set NO-ACK bit */
        macCtrl |= 0x4;
    }
    else
    {
        /* unicast frame */
    #if 0
        // Enable RTS according to MPDU Lengths ( not MSDU Lengths )
        if (len >= wd->rtsThreshold)
        {
            /* Enable RTS */
            macCtrl |= 1;
        }
    #endif
    }
    /* VAP test code */
    //macCtrl |= 0x4;

    if (wd->wlanMode == ZM_MODE_AP)
    {
        u8_t encryType;
        u16_t iv16;
        u32_t iv32;

        /* Check whether this is a multicast frame */
        if ((header[6] & 0x1) == 0x1)
        {
            /* multicast frame */
            if (wd->ap.encryMode[vap] == ZM_TKIP)
            {
                wd->ap.iv16[vap]++;

                if(wd->ap.iv16[vap] == 0)
                {
                    wd->ap.iv32[vap]++;
                }

                b1 = (u8_t) (wd->ap.iv16[vap] >> 8);
                b2 = (b1 | 0x20) & 0x7f;
                header[hlen] = ((u16_t)b2 << 8) + b1;
                b1 = (u8_t) wd->ap.iv16[vap];
                b2 = 0x20 | (wd->ap.bcKeyIndex[vap] << 6);
                header[hlen+1] = ((u16_t)b2 << 8) + b1;
                header[hlen+2] = (u16_t) wd->ap.iv32[vap];
                header[hlen+3] = (u16_t) (wd->ap.iv32[vap] >> 16);

                //macCtrl |= 0x80;
                macCtrl |= 0x40;
                icvLen = 4;

                /* set hardware MIC */
                if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
                {
                    macCtrl |= 0x100;
                    plusLen += 8;
                    *micLen = 8;
                }

                header[4] |= 0x4000;
                hlen += 4;
            }
            else if (wd->ap.encryMode[vap] == ZM_AES)
            {
                wd->ap.iv16[vap]++;

                if(wd->ap.iv16[vap] == 0)
                {
                    wd->ap.iv32[vap]++;
                }

                b1 = (u8_t) wd->ap.iv16[vap];
                b2 = (u8_t) (wd->ap.iv16[vap] >> 8);
                header[hlen] = ((u16_t)b2 << 8) + b1;
                header[hlen+1] = 0x2000 | (wd->ap.bcKeyIndex[vap] << 14);
                header[hlen+2] = (u16_t) (wd->ap.iv32[vap]);
                header[hlen+3] = (u16_t) (wd->ap.iv32[vap] >> 16);

                macCtrl |= 0xc0;
                icvLen = 8;  /* MIC */

                header[4] |= 0x4000;
                hlen += 4;
            }
            #ifdef ZM_ENABLE_CENC
            else if (wd->ap.encryMode[vap] == ZM_CENC)
            {
                //u32_t txiv[4];

                wd->ap.txiv[vap][0]++;

                if (wd->ap.txiv[vap][0] == 0)
                {
                    wd->ap.txiv[vap][1]++;
                }

                if (wd->ap.txiv[vap][1] == 0)
                {
                    wd->ap.txiv[vap][2]++;
                }

                if (wd->ap.txiv[vap][2] == 0)
                {
                    wd->ap.txiv[vap][3]++;
                }

                if (wd->ap.txiv[vap][3] == 0)
                {
                    wd->ap.txiv[vap][0] = 0;
                    wd->ap.txiv[vap][1] = 0;
                    wd->ap.txiv[vap][2] = 0;
                }

                header[hlen] = (wd->ap.bcKeyIndex[vap] & 0x0001);    /* For Key Id and reserved field */
                header[hlen+1] = (u16_t)wd->ap.txiv[vap][0];
                header[hlen+2] = (u16_t)(wd->ap.txiv[vap][0] >> 16);
                header[hlen+3] = (u16_t)wd->ap.txiv[vap][1];
                header[hlen+4] = (u16_t)(wd->ap.txiv[vap][1] >> 16);
                header[hlen+5] = (u16_t)wd->ap.txiv[vap][2];
                header[hlen+6] = (u16_t)(wd->ap.txiv[vap][2] >> 16);
                header[hlen+7] = (u16_t)wd->ap.txiv[vap][3];
                header[hlen+8] = (u16_t)(wd->ap.txiv[vap][3] >> 16);

                macCtrl |= 0x80;
                icvLen = 16;  /* MIC */

                header[4] |= 0x4000;
                hlen += 9;
            }
            #endif //ZM_ENABLE_CENC
        }
        else
        {
            /* Get STA's encryption type */
            zfApGetStaEncryType(dev, da, &encryType);

            if (encryType == ZM_TKIP)
            {
                /* Get iv16 and iv32 */
                zfApGetStaWpaIv(dev, da, &iv16, &iv32);

                iv16++;
                if (iv16 == 0)
                {
                    iv32++;
                }

                b1 = (u8_t) (iv16 >> 8);
                b2 = (b1 | 0x20) & 0x7f;
                header[hlen] = ((u16_t)b2 << 8) + b1;
                b1 = (u8_t) iv16;
                b2 = 0x20;
                header[hlen+1] = ((u16_t)b2 << 8) + b1;
                header[hlen+2] = (u16_t) iv32;
                header[hlen+3] = (u16_t) (iv32 >> 16);

                //macCtrl |= 0x80;
                macCtrl |= 0x40;
                icvLen = 4;

                /* set hardware MIC */
                if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
                {
                    macCtrl |= 0x100;
                    plusLen += 8;
                    *micLen = 8;
                }

                header[4] |= 0x4000;
                hlen += 4;

                /* Set iv16 and iv32 */
                zfApSetStaWpaIv(dev, da, iv16, iv32);
            }
            else if (encryType == ZM_AES)
            {
                /* Get iv16 and iv32 */
                zfApGetStaWpaIv(dev, da, &iv16, &iv32);

                iv16++;
                if (iv16 == 0)
                {
                    iv32++;
                }

                b1 = (u8_t) iv16;
                b2 = (u8_t) (iv16 >> 8);
                header[hlen] = ((u16_t)b2 << 8) + b1;
                header[hlen+1] = 0x2000;
                header[hlen+2] = (u16_t) (iv32);
                header[hlen+3] = (u16_t) (iv32 >> 16);

                macCtrl |= 0xc0;
                icvLen = 8;  /* MIC */

                header[4] |= 0x4000;
                hlen += 4;

                /* Set iv16 and iv32 */
                zfApSetStaWpaIv(dev, da, iv16, iv32);
            }
            #ifdef ZM_ENABLE_CENC
            else if (encryType == ZM_CENC)
            {
                u32_t txiv[4];
                u8_t keyIdx;

                /* Get CENC TxIV */
                zfApGetStaCencIvAndKeyIdx(dev, da, txiv, &keyIdx);

                txiv[0] += 2;

                if (txiv[0] == 0 || txiv[0] == 1)
                {
                    txiv[1]++;
                }

                if (txiv[1] == 0)
                {
                    txiv[2]++;
                }

                if (txiv[2] == 0)
                {
                    txiv[3]++;
                }

                if (txiv[3] == 0)
                {
                    txiv[0] = 0;
                    txiv[1] = 0;
                    txiv[2] = 0;
                }

                header[hlen] = (keyIdx & 0x0001);    /* For Key Id and reserved field */
                header[hlen+1] = (u16_t)txiv[0];
                header[hlen+2] = (u16_t)(txiv[0] >> 16);
                header[hlen+3] = (u16_t)txiv[1];
                header[hlen+4] = (u16_t)(txiv[1] >> 16);
                header[hlen+5] = (u16_t)txiv[2];
                header[hlen+6] = (u16_t)(txiv[2] >> 16);
                header[hlen+7] = (u16_t)txiv[3];
                header[hlen+8] = (u16_t)(txiv[3] >> 16);

                macCtrl |= 0x80;
                icvLen = 16;  /* MIC */

                header[4] |= 0x4000;
                hlen += 9;

                /* Set CENC IV */
                zfApSetStaCencIv(dev, da, txiv);
            }
            #endif //ZM_ENABLE_CENC
        }

        /* protection mode */
        if (wd->ap.protectionMode == 1)
        {
            /* Enable Self-CTS */
            macCtrl &= 0xFFFC;
            macCtrl |= 2;
        }

        /* Rate Control */
        if (port < 0x20)
        {
            /* AP */
            /* IV */
            if ((wd->ap.encryMode[vap] == ZM_WEP64) ||
                    (wd->ap.encryMode[vap] == ZM_WEP128) ||
                    (wd->ap.encryMode[vap] == ZM_WEP256))
            {
                header[4] |= 0x4000;
                header[hlen] = 0x0;   //IV
                header[hlen+1] = wd->ap.bcKeyIndex[vap] << 14; //IV with Keyid--CWYang(m)
                hlen += 2;
                icvLen = 4;
                macCtrl |= 0x40;
            }
        }
        else
        {
            /* WDS */

            /* TODO : Fixed rate to 54M */
            phyCtrl = 0xc0001;   //PHY control L

            /* WDS port checking */
            wdsPort = port - 0x20;
            if (wdsPort >= ZM_MAX_WDS_SUPPORT)
            {
                wdsPort = 0;
            }

            #if 1
            /* IV */
            switch (wd->ap.wds.encryMode[wdsPort])
            {
            case ZM_WEP64:
            case ZM_WEP128:
            case ZM_WEP256:
                    header[4] |= 0x4000;
                    header[hlen] = 0x0;   //IV
                    header[hlen+1] = wd->ap.bcKeyIndex[vap] << 14; //IV with Keyid
                    hlen += 2;
                    icvLen = 4;
                    macCtrl |= 0x40;
                    break;

            case ZM_TKIP:
                    wd->sta.iv16++;

                    if ( wd->sta.iv16 == 0 )
                    {
                        wd->sta.iv32++;
                    }

                    b1 = (u8_t) (wd->sta.iv16 >> 8);
                    b2 = (b1 | 0x20) & 0x7f;
                    header[hlen] = ((u16_t)b2 << 8) + b1;
                    b1 = (u8_t) wd->sta.iv16;
                    b2 = 0x20;
                    header[hlen+1] = ((u16_t)b2 << 8) + b1;
                    header[hlen+2] = (u16_t) wd->sta.iv32;
                    header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);

                    //macCtrl |= 0x80;
                    macCtrl |= 0x40;
                    icvLen = 4;

                    /* set hardware MIC */
                    if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
                    {
                        macCtrl |= 0x100;
                        plusLen += 8;
                        *micLen = 8;
                    }

                    header[4] |= 0x4000;
                    hlen += 4;
                    break;

            case ZM_AES:
                    wd->sta.iv16++;
                    if ( wd->sta.iv16 == 0 )
                    {
                        wd->sta.iv32++;
                    }

                    b1 = (u8_t) wd->sta.iv16;
                    b2 = (u8_t) (wd->sta.iv16 >> 8);
                    header[hlen] = ((u16_t)b2 << 8) + b1;
                    header[hlen+1] = 0x2000;
                    header[hlen+2] = (u16_t) (wd->sta.iv32);
                    header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);

                    macCtrl |= 0xc0; /* Set to AES in control setting */
                    icvLen = 8;  /* MIC */

                    header[4] |= 0x4000; /* Set WEP bit in wlan header */
                    hlen += 4; /* plus IV length */
                    break;
            }/* end of switch */
            #endif
        }
    }
    else   /* wd->wlanMode != ZM_MODE_AP */
    {
        encExemptionActionType = zfwGetPktEncExemptionActionType(dev, buf);

        if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
        {
            #if 1
            /* if WME AP */
            if (wd->sta.wmeConnected != 0)
            {
                /* QoS data */
                header[4] |= 0x0080;

                /* QoS Control */
                header[hlen] = up;
                hlen += 1;
            }
            #endif

            if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
            {
                if ( wd->sta.authMode < ZM_AUTH_MODE_WPA )
                {   /* non-WPA */
                    if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED )
                    {
                        if ( (wd->sta.encryMode == ZM_WEP64)||
                             (wd->sta.encryMode == ZM_WEP128)||
                             (wd->sta.encryMode == ZM_WEP256) )
                        {
                            header[4] |= 0x4000;
                            header[hlen] = 0x0;   //IV
                            header[hlen+1] = 0x0; //IV
                            header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
                            hlen += 2;
                            icvLen = 4;

                            /* For Software WEP */
                            if ((wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) != 0)
                            {
                                u8_t keyLen = 5;
                                u8_t iv[3];

                                iv[0] = 0x0;
                                iv[1] = 0x0;
                                iv[2] = 0x0;

                                if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP64)
                                {
                                    keyLen = 5;
                                }
                                else if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP128)
                                {
                                    keyLen = 13;
                                }
                                else if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP256)
                                {
                                    keyLen = 29;
                                }

                                zfWEPEncrypt(dev, buf, (u8_t*) snap, snapLen, minusLen, keyLen,
                                        wd->sta.wepKey[wd->sta.keyId], iv);
                            }
                            else
                            {
                                macCtrl |= 0x40;
                            }
                        }
                    }
                }
                else
                {   /* WPA */
                    if ( wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK )
                    {
                        wd->sta.iv16++;
                        if ( wd->sta.iv16 == 0 )
                        {
                            wd->sta.iv32++;
                        }

                        /* set encryption mode */
                        if ( wd->sta.encryMode == ZM_TKIP )
                        {
                            b1 = (u8_t) (wd->sta.iv16 >> 8);
                            b2 = (b1 | 0x20) & 0x7f;
                            header[hlen] = ((u16_t)b2 << 8) + b1;
                            b1 = (u8_t) wd->sta.iv16;
                            b2 = 0x20;

                            // header[hlen+1] = (((u16_t) wd->sta.keyId) << 14) | (((u16_t)b2 << 8) + b1);
                            // STA in infrastructure mode should use keyId = 0 to transmit unicast !
                            header[hlen+1] = (((u16_t)b2 << 8) + b1);
                            header[hlen+2] = (u16_t) wd->sta.iv32;
                            header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);

                            /* If software encryption enable */
                            if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0)
                            {
                                //macCtrl |= 0x80;
                                /* TKIP same to WEP */
                                macCtrl |= 0x40;
                                icvLen = 4;

                                /* set hardware MIC */
                                if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
                                {
                                    macCtrl |= 0x100;
                                    plusLen += 8;
                                    *micLen = 8;
                                }
                            }
                            else
                            {
                                u8_t mic[8];
                                u16_t offset;
                                u32_t icv;
                                u8_t RC4Key[16];

                                /* TODO: Remove the criticial section here. */
                                zmw_declare_for_critical_section();

                                zmw_enter_critical_section(dev);
                                /* Calculate MIC */
                                zfCalTxMic(dev, buf, (u8_t *)snap, snapLen, minusLen, da, sa, up, mic);

                                offset = zfwBufGetSize(dev, buf);

                                /* Append MIC to the buffer */
                                zfCopyToIntTxBuffer(dev, buf, mic, offset, 8);
                                zfwBufSetSize(dev, buf, offset+8);
                                zmw_leave_critical_section(dev);

                                /* TKIP Key Mixing */
                                zfTkipPhase1KeyMix(wd->sta.iv32, &wd->sta.txSeed);
                                zfTkipPhase2KeyMix(wd->sta.iv16, &wd->sta.txSeed);
                                zfTkipGetseeds(wd->sta.iv16, RC4Key, &wd->sta.txSeed);

                                /* Encrypt Data */
                                zfTKIPEncrypt(dev, buf, (u8_t *)snap, snapLen, minusLen, 16, RC4Key, &icv);

                                icvLen = 4;
                                len += 8;
                            }

                            header[4] |= 0x4000;
                            hlen += 4;
                        }
                        else if ( wd->sta.encryMode == ZM_AES )
                        {
                            b1 = (u8_t) wd->sta.iv16;
                            b2 = (u8_t) (wd->sta.iv16 >> 8);
                            header[hlen] = ((u16_t)b2 << 8) + b1;
                            // header[hlen+1] = (((u16_t) wd->sta.keyId) << 14) | (0x2000);
                            // STA in infrastructure mode should use keyId = 0 to transmit unicast !
                            header[hlen+1] = 0x2000;
                            header[hlen+2] = (u16_t) (wd->sta.iv32);
                            header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);

                            macCtrl |= 0xc0;
                            icvLen = 8;  /* MIC */

                            header[4] |= 0x4000;
                            hlen += 4;
                        }
                        #ifdef ZM_ENABLE_CENC
                        else if ( wd->sta.encryMode == ZM_CENC )
                        {
                            /* Accumlate the PN sequence */
                            wd->sta.txiv[0] += 2;

                            if (wd->sta.txiv[0] == 0 || wd->sta.txiv[0] == 1)
                            {
                                wd->sta.txiv[1]++;
                            }

                            if (wd->sta.txiv[1] == 0)
                            {
                                wd->sta.txiv[2]++;
                            }

                            if (wd->sta.txiv[2] == 0)
                            {
                                wd->sta.txiv[3]++;
                            }

                            if (wd->sta.txiv[3] == 0)
                            {
                                wd->sta.txiv[0] = 0;
                                wd->sta.txiv[1] = 0;
                                wd->sta.txiv[2] = 0;
                            }

                            header[hlen] = (wd->sta.cencKeyId & 0x0001);    /* For Key Id and reserved field */
                            header[hlen+1] = (u16_t) wd->sta.txiv[0];
                            header[hlen+2] = (u16_t) (wd->sta.txiv[0] >> 16);
                            header[hlen+3] = (u16_t) wd->sta.txiv[1];
                            header[hlen+4] = (u16_t) (wd->sta.txiv[1] >> 16);
                            header[hlen+5] = (u16_t) wd->sta.txiv[2];
                            header[hlen+6] = (u16_t) (wd->sta.txiv[2] >> 16);
                            header[hlen+7] = (u16_t) wd->sta.txiv[3];
                            header[hlen+8] = (u16_t) (wd->sta.txiv[3] >> 16);

                            macCtrl |= 0x80;
                            icvLen = 16;  /* MIC */

                            header[4] |= 0x4000;
                            hlen += 9;
                        }
                        #endif //ZM_ENABLE_CENC
                    }
                }
            } // if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
        } /* if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE ) */

        if ( wd->wlanMode == ZM_MODE_IBSS )
        {
            if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
            {
#ifdef ZM_ENABLE_IBSS_WPA2PSK
                if( wd->sta.oppositeInfo[userIdx].wpaState >= ZM_STA_WPA_STATE_PK_OK || wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK)
                {
                    int isUnicast = 1 ;

                    if((da[0]& 0x1))
                    {
                        isUnicast = 0 ; // Not unicast , is broadcast
                    }

                    if( wd->sta.ibssWpa2Psk == 1 )
                    { /* The IV order is not the same between unicast and broadcast ! */
                        if ( isUnicast )
                        {
                            iv16 = &wd->sta.oppositeInfo[userIdx].iv16;
                            iv32 = &wd->sta.oppositeInfo[userIdx].iv32;
                        }
                        else
                        {
                            iv16 = &wd->sta.iv16;
                            iv32 = &wd->sta.iv32;
                        }
                    }
                    else
                    {
                        iv16 = &wd->sta.iv16;
                        iv32 = &wd->sta.iv32;
                    }

                    (*iv16)++;
                    if ( *iv16 == 0 )
                    {
                        *iv32++;
                    }

                    if ( wd->sta.oppositeInfo[userIdx].encryMode == ZM_AES || wd->sta.encryMode == ZM_AES)
                    {
                        //printk("Station encryption mode is AES-CCMP\n") ;
                        b1 = (u8_t) (*iv16);
                        b2 = (u8_t) ((*iv16) >> 8);
                        header[hlen] = ((u16_t)b2 << 8) + b1;

                        if ( isUnicast )
                        {
                            header[hlen+1] = 0x2000;
                        }
                        else
                        {
                            header[hlen+1] = 0x2000 | (((u16_t) wd->sta.keyId) << 14);
                        }

                        header[hlen+2] = (u16_t) (*iv32);
                        header[hlen+3] = (u16_t) ((*iv32) >> 16);
                        macCtrl |= 0xc0;
                        icvLen = 8;  /* MIC */
                    }

                    header[4] |= 0x4000;
                    hlen += 4;
                }
                else if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED)
                {
                    if ( (wd->sta.encryMode == ZM_WEP64)||
                        (wd->sta.encryMode == ZM_WEP128)||
                        (wd->sta.encryMode == ZM_WEP256) )
                    {
                        header[4] |= 0x4000;
                        header[hlen] = 0x0;   //IV
                        header[hlen+1] = 0x0; //IV
                        header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
                        hlen += 2;
                        icvLen = 4;
                        macCtrl |= 0x40;
                    }
                }
#else
                /* ----- 20070405 add by Mxzeng ----- */
                if( wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK )
                {
                    int isUnicast = 1 ;

                    if((da[0]& 0x1))
                    {
                        isUnicast = 0 ; // Not unicast , is broadcast
                    }

                    wd->sta.iv16++;
                    if ( wd->sta.iv16 == 0 )
                    {
                        wd->sta.iv32++;
                    }

                    if ( wd->sta.encryMode == ZM_AES )
                    {
                        //printk("Station encryption mode is AES-CCMP\n") ;
                        b1 = (u8_t) wd->sta.iv16;
                        b2 = (u8_t) (wd->sta.iv16 >> 8);
                        header[hlen] = ((u16_t)b2 << 8) + b1;

                        if ( isUnicast )
                        {
                            header[hlen+1] = 0x2000;
                        }
                        else
                        {
                            header[hlen+1] = 0x2000 | (((u16_t) wd->sta.keyId) << 14);
                        }

                            header[hlen+2] = (u16_t) (wd->sta.iv32);
                            header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
                            macCtrl |= 0xc0;
                            icvLen = 8;  /* MIC */
                    }

                    header[4] |= 0x4000;
                    hlen += 4;
                }
                else if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED)
                {
                    if ( (wd->sta.encryMode == ZM_WEP64)||
                         (wd->sta.encryMode == ZM_WEP128)||
                         (wd->sta.encryMode == ZM_WEP256) )
                    {
                        header[4] |= 0x4000;
                        header[hlen] = 0x0;   //IV
                        header[hlen+1] = 0x0; //IV
                        header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
                        hlen += 2;
                        icvLen = 4;
                        macCtrl |= 0x40;
                    }
                }
#endif
            }   // End if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
        }   // End if ( wd->wlanMode == ZM_MODE_IBSS )
        else if ( wd->wlanMode == ZM_MODE_PSEUDO )
        {
            switch (wd->sta.encryMode)
	        {
            case ZM_WEP64:
            case ZM_WEP128:
            case ZM_WEP256:
                header[4] |= 0x4000;
                header[hlen] = 0x0;   //IV
                header[hlen+1] = 0x0; //IV
                hlen += 2;
                icvLen = 4;
                macCtrl |= 0x40;
                break;

            case ZM_TKIP:
            {
                wd->sta.iv16++;
                if ( wd->sta.iv16 == 0 )
                {
                    wd->sta.iv32++;
                }

                b1 = (u8_t) (wd->sta.iv16 >> 8);
                b2 = (b1 | 0x20) & 0x7f;
                header[hlen] = ((u16_t)b2 << 8) + b1;
                b1 = (u8_t) wd->sta.iv16;
                b2 = 0x20;
                header[hlen+1] = ((u16_t)b2 << 8) + b1;
                header[hlen+2] = (u16_t) wd->sta.iv32;
                header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);

                //macCtrl |= 0x80;
                macCtrl |= 0x40;
                icvLen = 4;

                /* set hardware MIC */
                if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
                {
                    macCtrl |= 0x100;
                    plusLen += 8;
                    *micLen = 8;
                }

                header[4] |= 0x4000;
                hlen += 4;
            }/* end of PSEUDO TKIP */
                break;

            case ZM_AES:
            {
                wd->sta.iv16++;
                if ( wd->sta.iv16 == 0 )
                {
                    wd->sta.iv32++;
                }

                b1 = (u8_t) wd->sta.iv16;
                b2 = (u8_t) (wd->sta.iv16 >> 8);
                header[hlen] = ((u16_t)b2 << 8) + b1;
                header[hlen+1] = 0x2000;
                header[hlen+2] = (u16_t) (wd->sta.iv32);
                header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
                macCtrl |= 0xc0;
                icvLen = 8;  /* MIC */
                header[4] |= 0x4000;
                hlen += 4;
            }/* end of PSEUDO AES */
                    break;

              #ifdef ZM_ENABLE_CENC
              case ZM_CENC:
                    /* Accumlate the PN sequence */
                    wd->sta.txiv[0] += 2;

                    if (wd->sta.txiv[0] == 0 || wd->sta.txiv[0] == 1)
                    {
                        wd->sta.txiv[1]++;
                    }

                    if (wd->sta.txiv[1] == 0)
                    {
                        wd->sta.txiv[2]++;
                    }

                    if (wd->sta.txiv[2] == 0)
                    {
                        wd->sta.txiv[3]++;
                    }

                    if (wd->sta.txiv[3] == 0)
                    {
                        wd->sta.txiv[0] = 0;
                        wd->sta.txiv[1] = 0;
                        wd->sta.txiv[2] = 0;
                    }

                    header[hlen] = 0;
                    header[hlen+1] = (u16_t) wd->sta.txiv[0];
                    header[hlen+2] = (u16_t) (wd->sta.txiv[0] >> 16);
                    header[hlen+3] = (u16_t) wd->sta.txiv[1];
                    header[hlen+4] = (u16_t) (wd->sta.txiv[1] >> 16);
                    header[hlen+5] = (u16_t) wd->sta.txiv[2];
                    header[hlen+6] = (u16_t) (wd->sta.txiv[2] >> 16);
                    header[hlen+7] = (u16_t) wd->sta.txiv[3];
                    header[hlen+8] = (u16_t) (wd->sta.txiv[3] >> 16);

                    macCtrl |= 0x80;
                    icvLen = 16;  /* MIC */

                    header[4] |= 0x4000;
                    hlen += 9;
				break;
		    #endif //ZM_ENABLE_CENC
			}/* end of switch */
		}

        /* Generate control setting */

        /* protection mode */
        if (wd->enableProtectionMode)
        {
            if (wd->enableProtectionMode==2)
            {
                /* Force enable protection: self cts  */
                macCtrl &= 0xFFFC;
                macCtrl |= 2;
            }
            /* if wd->enableProtectionMode=1 => force disable */
            /* if wd->enableProtectionMode=0 => auto */
        }
        else
        {

            /* protection mode */
            if (wd->sta.bProtectionMode == TRUE)
            {
                /* Enable Self-CTS */
                macCtrl &= 0xFFFC;
                macCtrl |= 2;
            }
        }

    }

    if (wd->txMCS != 0xff)
    {
        /* fixed rate */
	    phyCtrl = ((u32_t)wd->txMCS<<16) + wd->txMT;
        mcs = wd->txMCS;
        mt = wd->txMT;
    }

    if (mt == 2)
    {
#if 0
        /* HT PT: 0 Mixed mode    1 Green field */
	    if (wd->sta.preambleTypeHT == ZM_PREAMBLE_TYPE_GREEN_FIELD)
	    {
            phyCtrl |= 0x4;     /* Bit 2 */
        }
#endif
        /* Bandwidth */
        if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
        {
            phyCtrl |= (0x80<<16);  /* BIT 23 */
        }
#if 0
        /* STBC */
        if (wd->sta.htCtrlSTBC<=0x3)
        {
            phyCtrl |= (wd->sta.htCtrlSTBC<<28);   /* BIT 23 */
        }
#endif
        /* Short GI */
        if(wd->sta.htCtrlSG)
        {
            phyCtrl |= (0x8000<<16);         /* BIT 31 */
        }

        /* TA */
        if ( ((mcs >=0x8) && (mcs<=0xf))  || (wd->sta.htCtrlSTBC) )
        {
       	    phyCtrl |= 0x1800;               /* BIT 11 12 */
    	}
    }
    else if(mt == 1)
    {
        #if 0
        //bug that cause OFDM rate become duplicate legacy rate
        /* Bandwidth */
        if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
        {
            phyCtrl |= (0x80<<16);  /* BIT 23 */
            mt = 3;                 /* duplicate legacy */
            phyCtrl |= mt;
        }
        #endif
    }
    else if(mt == 0)
    {
	/* CCK PT: Legcy Preamble: 1 long preamble    2 short preamble */
        if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_SHORT)
        {
    	       //phyCtrl |= 0x4;    /* BIT 2 */
    	}
    }

    /* TA */
    if (wd->sta.defaultTA)
    {
        phyCtrl |= 0x1000;
    }
    else
    {
        phyCtrl |= 0x0800;
    }

    //Get CurrentTxRate -- CWYang(+)
    if ((mt == 0) || (mt == 1)) //B,G Rate
    {
        if (mcs < 16)
        {
            wd->CurrentTxRateKbps = zcIndextoRateBG[mcs];
        }
    }
    else if (mt == 2)
    {
        if (mcs < 16)
        {
            if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
            {
                if((phyCtrl & 0x80000000) != 0)
                {
                    /* Short GI 40 MHz MIMO Rate */
                    wd->CurrentTxRateKbps = zcIndextoRateN40S[mcs];
                }
                else
                {
                    /* Long GI 40 MHz MIMO Rate */
                    wd->CurrentTxRateKbps = zcIndextoRateN40L[mcs];
                }
            }
            else
            {
                if((phyCtrl & 0x80000000) != 0)
                {
                    /* Short GI 20 MHz MIMO Rate */
                    wd->CurrentTxRateKbps = zcIndextoRateN20S[mcs];
                }
                else
                {
                    /* Long GI 20 MHz MIMO Rate */
                    wd->CurrentTxRateKbps = zcIndextoRateN20L[mcs];
                }
            }
        }
    }

    //802.11 header(include IV) = (hlen<<1)-8
    //ethernet frame = len
    //snap + mic = plusLen
    //ethernet header = minusLen
    //icv = icvLen
    //crc32 = 4
    //length=802.11 header+snap+(ethernet frame-ethernet header)+mic+icv+crc32
    header[0] = ((hlen<<1)-8)+plusLen+(len-minusLen)+icvLen+4;  //Length

    // header[0] : MPDU Lengths
    if ((header[6] & 0x1) != 0x1) // Unicast Frame
    {
        if (header[0] >= wd->rtsThreshold)
        {
            /* Enable RTS */
            macCtrl |= 1;
        }
    }

    if ( wd->sta.encryMode == ZM_TKIP )
        tkipFrameOffset = 8;

    if( wd->sta.EnableHT != 1 )
    { // Aggregation should not be fragmented !
        if ( header[0] > ( wd->fragThreshold + tkipFrameOffset ) )
        {
            return 0; // Need to be fragmented ! !
        }
    }

    //if ( wd->sta.encryMode == ZM_TKIP )
    //{
    //    zm_debug_msg1("ctrl length = ", header[0]);
    //}

    //MAC control
    if (rateProbingFlag != 0)
    {
        macCtrl |= 0x8000;
    }
    header[1] = macCtrl;
    //PHY control L
    header[2] = (u16_t) ((phyCtrl&0xffff) | 0x700 | (zcUpToAc[up&0x7]<<13));
    //PHY control H
    header[3] = (u16_t) ((phyCtrl>>16) | 0x700);

    if (wd->enableAggregation)
    {
        /* force enable aggregation */
        if (wd->enableAggregation==2 && !(header[6]&0x1))
        {
            if (((header[2] & 0x3) == 2))
            {
                /* Enable aggregation */
                header[1] |= 0x20;
            }
        }
        /* if wd->enableAggregation=1 => force disable */
        /* if wd->enableAggregation=0 => auto */
    }

#ifdef ZM_ENABLE_AGGREGATION
    if (wd->addbaComplete) {
        #ifdef ZM_BYPASS_AGGR_SCHEDULING
        if (!(header[6]&0x1) && !rateProbingFlag && (wd->enableAggregation != 1))
        {
            if (((header[2] & 0x3) == 2))
            {
                /* Unicast frame with HT rate => Enable aggregation */
                /* We only support software encryption in single packet mode */
                if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0 &&
                    (wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) == 0)
                {
                    /* Set aggregation group bits per AC */
                    header[1] |= (0x20 | (zcUpToAc[up&0x7]<<10));

                    //if (wd->sta.currentFrequency < 3000)
                    {
                        /* issue: -PB42 Enable RTS/CTS to prevent OWL Tx hang up */
                        /* If this is Owl Ap, enable RTS/CTS protect */
                        if ( (wd->sta.athOwlAp == 1) || (wd->sta.RTSInAGGMode == TRUE) )
                        {
                            header[1] &= 0xfffc;
                            header[1] |= 0x1;
                        }

                        /* Enable RIFS : workaround 854T RTS/CTS */
                        /* Bit13 : TI enable RIFS */
                        //header[1] |= 0x2000;
                    }
                }
            }
        }
        #else
        /*
         * aggregation ampduIndication control
         */
        if (aggControl && aggControl->aggEnabled) {
            if (wd->enableAggregation==0 && !(header[6]&0x1))
            {
                if (((header[2] & 0x3) == 2))
                {
                    /* Enable aggregation */
                    header[1] |= 0x20;
                    if (ZM_AGG_LAST_MPDU == aggControl->ampduIndication)
                        header[1] |= 0x4000;
                }
                else {
                    zm_debug_msg1("no aggr, header[2]&0x3 = ",header[2] & 0x3)
                    aggControl->aggEnabled = 0;
                }
            }
            else {
                zm_debug_msg1("no aggr, wd->enableAggregation = ", wd->enableAggregation);
                zm_debug_msg1("no aggr, !header[6]&0x1 = ",!(header[6]&0x1));
                aggControl->aggEnabled = 0;
            }
        }
        #endif

        #ifdef ZM_AGGR_BIT_ON
        if (!(header[6]&0x1) && !rateProbingFlag)
        {
            if (((header[2] & 0x3) == 2))
            {
                /* Unicast frame with HT rate => Enable aggregation */
                /* Set aggregation group bits per AC */
                header[1] |= (0x20 | (zcUpToAc[up&0x7]<<10));

                //if (wd->sta.currentFrequency < 3000)
                {
                    /* Enable RTS/CTS to prevent OWL Tx hang up */
                    header[1] &= 0xfffc;
                    header[1] |= 0x1;
                }
            }
        }
        #endif
    }
#endif

    return (hlen<<1);
}

Generated by GNU enscript 1.6.4.