Commit | Line | Data |
---|---|---|
5449c685 FB |
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 | ||
5449c685 | 34 | #include "ttype.h" |
5449c685 | 35 | #include "tmacro.h" |
5449c685 | 36 | #include "tether.h" |
5449c685 | 37 | #include "IEEE11h.h" |
5449c685 | 38 | #include "device.h" |
5449c685 | 39 | #include "wmgr.h" |
5449c685 | 40 | #include "rxtx.h" |
79566eb2 | 41 | #include "channel.h" |
5449c685 FB |
42 | |
43 | /*--------------------- Static Definitions -------------------------*/ | |
51ce068c | 44 | static int msglevel = MSG_LEVEL_INFO; |
5449c685 FB |
45 | |
46 | #pragma pack(1) | |
47 | ||
48 | typedef struct _WLAN_FRAME_ACTION { | |
51ce068c TS |
49 | WLAN_80211HDR_A3 Header; |
50 | unsigned char byCategory; | |
51 | unsigned char byAction; | |
52 | unsigned char abyVars[1]; | |
5449c685 FB |
53 | } WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION; |
54 | ||
55 | typedef struct _WLAN_FRAME_MSRREQ { | |
51ce068c TS |
56 | WLAN_80211HDR_A3 Header; |
57 | unsigned char byCategory; | |
58 | unsigned char byAction; | |
59 | unsigned char byDialogToken; | |
60 | WLAN_IE_MEASURE_REQ sMSRReqEIDs[1]; | |
5449c685 FB |
61 | } WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ; |
62 | ||
63 | typedef struct _WLAN_FRAME_MSRREP { | |
51ce068c TS |
64 | WLAN_80211HDR_A3 Header; |
65 | unsigned char byCategory; | |
66 | unsigned char byAction; | |
67 | unsigned char byDialogToken; | |
68 | WLAN_IE_MEASURE_REP sMSRRepEIDs[1]; | |
5449c685 FB |
69 | } WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP; |
70 | ||
71 | typedef struct _WLAN_FRAME_TPCREQ { | |
51ce068c TS |
72 | WLAN_80211HDR_A3 Header; |
73 | unsigned char byCategory; | |
74 | unsigned char byAction; | |
75 | unsigned char byDialogToken; | |
76 | WLAN_IE_TPC_REQ sTPCReqEIDs; | |
5449c685 FB |
77 | } WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ; |
78 | ||
79 | typedef struct _WLAN_FRAME_TPCREP { | |
51ce068c TS |
80 | WLAN_80211HDR_A3 Header; |
81 | unsigned char byCategory; | |
82 | unsigned char byAction; | |
83 | unsigned char byDialogToken; | |
84 | WLAN_IE_TPC_REP sTPCRepEIDs; | |
5449c685 FB |
85 | } WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP; |
86 | ||
87 | #pragma pack() | |
88 | ||
51ce068c | 89 | /* action field reference ieee 802.11h Table 20e */ |
5449c685 FB |
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 --------------------------*/ | |
7b6a0013 | 101 | static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq, |
b6e95cd5 | 102 | unsigned int uLength) |
5449c685 | 103 | { |
51ce068c TS |
104 | size_t uNumOfEIDs = 0; |
105 | bool bResult = true; | |
106 | ||
107 | if (uLength <= WLAN_A3FR_MAXLEN) | |
108 | memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength); | |
109 | uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ, | |
110 | sMSRReqEIDs))/ | |
111 | (sizeof(WLAN_IE_MEASURE_REQ))); | |
112 | pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP) | |
113 | (pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]); | |
114 | pMgmt->uLengthOfRepEIDs = 0; | |
115 | bResult = CARDbStartMeasure(pMgmt->pAdapter, | |
116 | ((PWLAN_FRAME_MSRREQ) | |
117 | (pMgmt->abyCurrentMSRReq))->sMSRReqEIDs, | |
118 | uNumOfEIDs | |
119 | ); | |
120 | return bResult; | |
5449c685 FB |
121 | } |
122 | ||
123 | ||
51ce068c TS |
124 | static bool s_bRxTPCReq(PSMgmtObject pMgmt, |
125 | PWLAN_FRAME_TPCREQ pTPCReq, | |
126 | unsigned char byRate, | |
127 | unsigned char byRSSI) | |
5449c685 | 128 | { |
51ce068c TS |
129 | PWLAN_FRAME_TPCREP pFrame; |
130 | PSTxMgmtPacket pTxPacket = NULL; | |
131 | ||
132 | pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool; | |
133 | memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); | |
134 | pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + | |
135 | sizeof(STxMgmtPacket)); | |
136 | ||
137 | pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket + | |
138 | sizeof(STxMgmtPacket)); | |
139 | ||
140 | pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | | |
141 | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) | |
142 | ); | |
143 | ||
144 | memcpy(pFrame->Header.abyAddr1, | |
145 | pTPCReq->Header.abyAddr2, | |
146 | WLAN_ADDR_LEN); | |
147 | memcpy(pFrame->Header.abyAddr2, | |
148 | CARDpGetCurrentAddress(pMgmt->pAdapter), | |
149 | WLAN_ADDR_LEN); | |
150 | memcpy(pFrame->Header.abyAddr3, | |
151 | pMgmt->abyCurrBSSID, | |
152 | WLAN_BSSID_LEN); | |
153 | ||
154 | pFrame->byCategory = 0; | |
155 | pFrame->byAction = 3; | |
156 | pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ) | |
157 | (pMgmt->abyCurrentMSRReq))->byDialogToken; | |
158 | ||
159 | pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP; | |
160 | pFrame->sTPCRepEIDs.len = 2; | |
161 | pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter); | |
162 | switch (byRate) { | |
163 | case RATE_54M: | |
164 | pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI; | |
165 | break; | |
166 | case RATE_48M: | |
167 | pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI; | |
168 | break; | |
169 | case RATE_36M: | |
170 | pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI; | |
171 | break; | |
172 | case RATE_24M: | |
173 | pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI; | |
174 | break; | |
175 | case RATE_18M: | |
176 | pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI; | |
177 | break; | |
178 | case RATE_12M: | |
179 | pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI; | |
180 | break; | |
181 | case RATE_9M: | |
182 | pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI; | |
183 | break; | |
184 | case RATE_6M: | |
185 | default: | |
186 | pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI; | |
187 | break; | |
188 | } | |
189 | ||
190 | pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP); | |
191 | pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) - | |
192 | WLAN_HDR_ADDR3_LEN; | |
193 | if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) | |
194 | return false; | |
195 | return true; | |
196 | /* return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG, | |
197 | sizeof(WLAN_FRAME_TPCREP))); */ | |
5449c685 FB |
198 | |
199 | } | |
200 | ||
201 | ||
202 | /*--------------------- Export Variables --------------------------*/ | |
203 | ||
204 | /*--------------------- Export Functions --------------------------*/ | |
205 | ||
206 | ||
207 | /*+ | |
208 | * | |
209 | * Description: | |
210 | * Handles action management frames. | |
211 | * | |
212 | * Parameters: | |
213 | * In: | |
214 | * pMgmt - Management Object structure | |
215 | * pRxPacket - Received packet | |
216 | * Out: | |
217 | * none | |
218 | * | |
219 | * Return Value: None. | |
220 | * | |
221 | -*/ | |
7b6a0013 | 222 | bool |
51ce068c | 223 | IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket) |
5449c685 | 224 | { |
51ce068c TS |
225 | PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; |
226 | PWLAN_FRAME_ACTION pAction = NULL; | |
227 | unsigned int uLength = 0; | |
228 | PWLAN_IE_CH_SW pChannelSwitch = NULL; | |
229 | ||
230 | /* decode the frame */ | |
231 | uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen; | |
232 | if (uLength > WLAN_A3FR_MAXLEN) | |
233 | return false; | |
234 | ||
235 | pAction = (PWLAN_FRAME_ACTION) | |
236 | (((PSRxMgmtPacket)pRxPacket)->p80211Header); | |
237 | ||
238 | if (pAction->byCategory == 0) { | |
239 | switch (pAction->byAction) { | |
240 | case ACTION_MSRREQ: | |
241 | return s_bRxMSRReq(pMgmt, | |
242 | (PWLAN_FRAME_MSRREQ) | |
243 | pAction, | |
244 | uLength); | |
245 | break; | |
246 | case ACTION_MSRREP: | |
247 | break; | |
248 | case ACTION_TPCREQ: | |
249 | return s_bRxTPCReq(pMgmt, | |
250 | (PWLAN_FRAME_TPCREQ) pAction, | |
251 | ((PSRxMgmtPacket)pRxPacket)->byRxRate, | |
252 | (unsigned char) | |
253 | ((PSRxMgmtPacket)pRxPacket)->uRSSI); | |
254 | break; | |
255 | case ACTION_TPCREP: | |
256 | break; | |
257 | case ACTION_CHSW: | |
258 | pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars); | |
259 | if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH) | |
260 | && (pChannelSwitch->len == 3)) { | |
261 | /* valid element id */ | |
262 | CARDbChannelSwitch(pMgmt->pAdapter, | |
263 | pChannelSwitch->byMode, | |
264 | get_channel_mapping(pMgmt->pAdapter, | |
265 | pChannelSwitch->byChannel, | |
266 | pMgmt->eCurrentPHYMode), | |
267 | pChannelSwitch->byCount); | |
268 | } | |
269 | break; | |
270 | default: | |
271 | DBG_PRT(MSG_LEVEL_DEBUG, | |
272 | KERN_INFO"Unknown Action = %d\n", | |
273 | pAction->byAction); | |
274 | break; | |
275 | } | |
276 | } else { | |
277 | DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n", | |
278 | pAction->byCategory); | |
279 | pAction->byCategory |= 0x80; | |
280 | ||
281 | /*return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG, | |
282 | uLength));*/ | |
283 | return true; | |
284 | } | |
285 | return true; | |
5449c685 FB |
286 | } |
287 | ||
288 | ||
51ce068c | 289 | bool IEEE11hbMSRRepTx(void *pMgmtHandle) |
5449c685 | 290 | { |
51ce068c TS |
291 | PSMgmtObject pMgmt = (PSMgmtObject) pMgmtHandle; |
292 | PWLAN_FRAME_MSRREP pMSRRep = (PWLAN_FRAME_MSRREP) | |
293 | (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket)); | |
294 | size_t uLength = 0; | |
295 | PSTxMgmtPacket pTxPacket = NULL; | |
296 | ||
297 | pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep; | |
298 | memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN); | |
299 | pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + | |
300 | sizeof(STxMgmtPacket)); | |
301 | ||
302 | pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) | | |
303 | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION) | |
304 | ); | |
305 | ||
306 | memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ) | |
307 | (pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN); | |
308 | memcpy(pMSRRep->Header.abyAddr2, | |
309 | CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN); | |
310 | memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN); | |
311 | ||
312 | pMSRRep->byCategory = 0; | |
313 | pMSRRep->byAction = 1; | |
314 | pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ) | |
315 | (pMgmt->abyCurrentMSRReq))->byDialogToken; | |
316 | ||
317 | uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP, | |
318 | sMSRRepEIDs); | |
319 | ||
320 | pTxPacket->cbMPDULen = uLength; | |
321 | pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN; | |
322 | if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING) | |
323 | return false; | |
324 | return true; | |
325 | /* return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG, | |
326 | uLength)); */ | |
5449c685 FB |
327 | |
328 | } | |
329 |