Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / drivers / staging / vt6655 / IEEE11h.c
1 /*
2  * Copyright (c) 1996, 2005 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  *
20  * File: IEEE11h.c
21  *
22  * Purpose:
23  *
24  * Functions:
25  *
26  * Revision History:
27  *
28  * Author: Yiching Chen
29  *
30  * Date: Mar. 31, 2005
31  *
32  */
33
34 #include "ttype.h"
35 #include "tmacro.h"
36 #include "tether.h"
37 #include "IEEE11h.h"
38 #include "device.h"
39 #include "wmgr.h"
40 #include "rxtx.h"
41 #include "channel.h"
42
43 /*---------------------  Static Definitions -------------------------*/
44 static int          msglevel                =MSG_LEVEL_INFO;
45
46 #pragma pack(1)
47
48 typedef struct _WLAN_FRAME_ACTION {
49     WLAN_80211HDR_A3    Header;
50     unsigned char byCategory;
51     unsigned char byAction;
52     unsigned char abyVars[1];
53 } WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION;
54
55 typedef struct _WLAN_FRAME_MSRREQ {
56     WLAN_80211HDR_A3    Header;
57     unsigned char byCategory;
58     unsigned char byAction;
59     unsigned char byDialogToken;
60     WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
61 } WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ;
62
63 typedef struct _WLAN_FRAME_MSRREP {
64     WLAN_80211HDR_A3    Header;
65     unsigned char byCategory;
66     unsigned char byAction;
67     unsigned char byDialogToken;
68     WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
69 } WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP;
70
71 typedef struct _WLAN_FRAME_TPCREQ {
72     WLAN_80211HDR_A3    Header;
73     unsigned char byCategory;
74     unsigned char byAction;
75     unsigned char byDialogToken;
76     WLAN_IE_TPC_REQ     sTPCReqEIDs;
77 } WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ;
78
79 typedef struct _WLAN_FRAME_TPCREP {
80     WLAN_80211HDR_A3    Header;
81     unsigned char byCategory;
82     unsigned char byAction;
83     unsigned char byDialogToken;
84     WLAN_IE_TPC_REP     sTPCRepEIDs;
85 } WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP;
86
87 #pragma pack()
88
89 // action field reference ieee 802.11h Table 20e
90 #define ACTION_MSRREQ       0
91 #define ACTION_MSRREP       1
92 #define ACTION_TPCREQ       2
93 #define ACTION_TPCREP       3
94 #define ACTION_CHSW         4
95
96 /*---------------------  Static Classes  ----------------------------*/
97
98 /*---------------------  Static Variables  --------------------------*/
99
100 /*---------------------  Static Functions  --------------------------*/
101 static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
102                 unsigned int uLength)
103 {
104     size_t    uNumOfEIDs = 0;
105     bool bResult = true;
106
107     if (uLength <= WLAN_A3FR_MAXLEN) {
108         memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
109     }
110     uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, sMSRReqEIDs))/ (sizeof(WLAN_IE_MEASURE_REQ)));
111     pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
112     pMgmt->uLengthOfRepEIDs = 0;
113     bResult = CARDbStartMeasure(pMgmt->pAdapter,
114                                 ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
115                                 uNumOfEIDs
116                                 );
117     return (bResult);
118 }
119
120
121 static bool s_bRxTPCReq(PSMgmtObject pMgmt, PWLAN_FRAME_TPCREQ pTPCReq, unsigned char byRate, unsigned char byRSSI)
122 {
123     PWLAN_FRAME_TPCREP  pFrame;
124     PSTxMgmtPacket      pTxPacket = NULL;
125
126
127     pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
128     memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
129     pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
130
131     pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
132
133     pFrame->Header.wFrameCtl = (   WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
134                                     WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
135                                 );
136
137     memcpy( pFrame->Header.abyAddr1, pTPCReq->Header.abyAddr2, WLAN_ADDR_LEN);
138     memcpy( pFrame->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
139     memcpy( pFrame->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
140
141     pFrame->byCategory = 0;
142     pFrame->byAction = 3;
143     pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
144
145     pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
146     pFrame->sTPCRepEIDs.len = 2;
147     pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
148     switch (byRate) {
149         case RATE_54M:
150             pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
151             break;
152         case RATE_48M:
153             pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
154             break;
155         case RATE_36M:
156             pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
157             break;
158         case RATE_24M:
159             pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
160             break;
161         case RATE_18M:
162             pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
163             break;
164         case RATE_12M:
165             pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
166             break;
167         case RATE_9M:
168             pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
169             break;
170         case RATE_6M:
171         default:
172             pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
173             break;
174     }
175
176     pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
177     pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - WLAN_HDR_ADDR3_LEN;
178     if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
179         return (false);
180     return (true);
181 //    return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, sizeof(WLAN_FRAME_TPCREP)));
182
183 }
184
185
186 /*---------------------  Export Variables  --------------------------*/
187
188 /*---------------------  Export Functions  --------------------------*/
189
190
191 /*+
192  *
193  * Description:
194  *      Handles action management frames.
195  *
196  * Parameters:
197  *  In:
198  *      pMgmt           - Management Object structure
199  *      pRxPacket       - Received packet
200  *  Out:
201  *      none
202  *
203  * Return Value: None.
204  *
205 -*/
206 bool
207 IEEE11hbMgrRxAction (
208     void *pMgmtHandle,
209     void *pRxPacket
210     )
211 {
212     PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
213     PWLAN_FRAME_ACTION      pAction = NULL;
214     unsigned int uLength = 0;
215     PWLAN_IE_CH_SW          pChannelSwitch = NULL;
216
217
218     // decode the frame
219     uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
220     if (uLength > WLAN_A3FR_MAXLEN) {
221         return (false);
222     }
223
224
225     pAction = (PWLAN_FRAME_ACTION) (((PSRxMgmtPacket)pRxPacket)->p80211Header);
226
227     if (pAction->byCategory == 0) {
228         switch (pAction->byAction) {
229             case ACTION_MSRREQ:
230                 return (s_bRxMSRReq(pMgmt, (PWLAN_FRAME_MSRREQ) pAction, uLength));
231                 break;
232             case ACTION_MSRREP:
233                 break;
234             case ACTION_TPCREQ:
235                 return (s_bRxTPCReq(pMgmt,
236                                     (PWLAN_FRAME_TPCREQ) pAction,
237                                     ((PSRxMgmtPacket)pRxPacket)->byRxRate,
238                                     (unsigned char) ((PSRxMgmtPacket)pRxPacket)->uRSSI));
239                 break;
240             case ACTION_TPCREP:
241                 break;
242             case ACTION_CHSW:
243                 pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
244                 if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) &&
245                     (pChannelSwitch->len == 3)) {
246                     // valid element id
247                     CARDbChannelSwitch( pMgmt->pAdapter,
248                                         pChannelSwitch->byMode,
249                                         get_channel_mapping(pMgmt->pAdapter, pChannelSwitch->byChannel, pMgmt->eCurrentPHYMode),
250                                         pChannelSwitch->byCount
251                                         );
252                 }
253                 break;
254             default:
255                 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Action = %d\n", pAction->byAction);
256                 break;
257         }
258     } else {
259         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", pAction->byCategory);
260         pAction->byCategory |= 0x80;
261
262        //return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, uLength));
263         return (true);
264     }
265     return (true);
266 }
267
268
269 bool IEEE11hbMSRRepTx (
270     void *pMgmtHandle
271     )
272 {
273     PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
274     PWLAN_FRAME_MSRREP      pMSRRep = (PWLAN_FRAME_MSRREP) (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
275     size_t                    uLength = 0;
276     PSTxMgmtPacket          pTxPacket = NULL;
277
278     pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
279     memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
280     pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
281
282
283     pMSRRep->Header.wFrameCtl = (   WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
284                                     WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
285                                 );
286
287     memcpy( pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
288     memcpy( pMSRRep->Header.abyAddr2, CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
289     memcpy( pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
290
291     pMSRRep->byCategory = 0;
292     pMSRRep->byAction = 1;
293     pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) (pMgmt->abyCurrentMSRReq))->byDialogToken;
294
295     uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, sMSRRepEIDs);
296
297     pTxPacket->cbMPDULen = uLength;
298     pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
299     if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
300         return (false);
301     return (true);
302 //    return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, uLength));
303
304 }
305