Commit | Line | Data |
---|---|---|
4bd43f50 LR |
1 | /* |
2 | * Copyright (c) 2007-2008 Atheros Communications Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | /* */ | |
17 | /* Module Name : mm.c */ | |
18 | /* */ | |
19 | /* Abstract */ | |
20 | /* This module contains common functions for handle management */ | |
21 | /* frame. */ | |
22 | /* */ | |
23 | /* NOTES */ | |
24 | /* None */ | |
25 | /* */ | |
26 | /************************************************************************/ | |
27 | #include "cprecomp.h" | |
28 | #include "../hal/hpreg.h" | |
29 | ||
30 | /* TODO : put all constant tables to a file */ | |
31 | const u8_t zg11bRateTbl[4] = {2, 4, 11, 22}; | |
32 | const u8_t zg11gRateTbl[8] = {12, 18, 24, 36, 48, 72, 96, 108}; | |
33 | ||
34 | /* 0xff => element does not exist */ | |
35 | const u8_t zgElementOffsetTable[] = | |
36 | { | |
37 | 4, /* 0 : asoc req */ | |
38 | 6, /* 1 : asoc rsp */ | |
39 | 10, /* 2 : reasoc req*/ | |
40 | 6, /* 3 : reasoc rsp */ | |
41 | 0, /* 4 : probe req */ | |
42 | 12, /* 5 : probe rsp */ | |
43 | 0xff, /* 6 : reserved */ | |
44 | 0xff, /* 7 : reserved */ | |
45 | 12, /* 8 : beacon */ | |
46 | 4, /* 9 : ATIM */ | |
47 | 0xff, /* 10 : disasoc */ | |
48 | 6, /* 11 : auth */ | |
49 | 0xff, /* 12 : deauth */ | |
50 | 4, /* 13 : action */ | |
51 | 0xff, /* 14 : reserved */ | |
52 | 0xff, /* 15 : reserved */ | |
53 | }; | |
54 | ||
55 | /************************************************************************/ | |
56 | /* */ | |
57 | /* FUNCTION DESCRIPTION zfFindElement */ | |
58 | /* Find a specific element in management frame */ | |
59 | /* */ | |
60 | /* INPUTS */ | |
61 | /* dev : device pointer */ | |
62 | /* buf : management frame buffer */ | |
63 | /* eid : target element id */ | |
64 | /* */ | |
65 | /* OUTPUTS */ | |
66 | /* byte offset of target element */ | |
67 | /* or 0xffff if not found */ | |
68 | /* */ | |
69 | /* AUTHOR */ | |
70 | /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ | |
71 | /* */ | |
72 | /************************************************************************/ | |
73 | u16_t zfFindElement(zdev_t* dev, zbuf_t* buf, u8_t eid) | |
74 | { | |
75 | u8_t subType; | |
76 | u16_t offset; | |
77 | u16_t bufLen; | |
78 | u16_t elen; | |
79 | u8_t id, HTEid=0; | |
80 | u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01}; | |
81 | u8_t oui11n[3] = {0x00,0x90,0x4C}; | |
82 | u8_t HTType = 0; | |
83 | ||
84 | /* Get offset of first element */ | |
85 | subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4); | |
92363b52 JP |
86 | offset = zgElementOffsetTable[subType]; |
87 | if (offset == 0xff) | |
4bd43f50 LR |
88 | { |
89 | zm_assert(0); | |
90 | } | |
91 | ||
92 | /* Plus wlan header */ | |
93 | offset += 24; | |
94 | ||
95 | // jhlee HT 0 | |
96 | ||
97 | if ((eid == ZM_WLAN_EID_HT_CAPABILITY) || | |
98 | (eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) | |
99 | { | |
100 | HTEid = eid; | |
101 | eid = ZM_WLAN_EID_WPA_IE; | |
102 | HTType = 1; | |
103 | } | |
104 | ||
105 | ||
106 | bufLen = zfwBufGetSize(dev, buf); | |
107 | /* Search loop */ | |
108 | while ((offset+2)<bufLen) // including element ID and length (2bytes) | |
109 | { | |
110 | /* Search target element */ | |
92363b52 JP |
111 | id = zmw_rx_buf_readb(dev, buf, offset); |
112 | if (id == eid) | |
4bd43f50 LR |
113 | { |
114 | /* Bingo */ | |
92363b52 JP |
115 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
116 | if (elen > bufLen - offset) | |
4bd43f50 LR |
117 | { |
118 | /* Element length error */ | |
119 | return 0xffff; | |
120 | } | |
121 | ||
122 | if ( elen == 0 && eid != ZM_WLAN_EID_SSID) | |
123 | { | |
124 | /* Element length error */ | |
125 | return 0xffff; | |
126 | } | |
127 | ||
128 | if ( eid == ZM_WLAN_EID_WPA_IE ) | |
129 | { | |
130 | /* avoid sta to be thought use 11n when find a WPA_IE */ | |
131 | if ( (HTType == 0) && zfRxBufferEqualToStr(dev, buf, oui, offset+2, 4) ) | |
132 | { | |
133 | return offset; | |
134 | } | |
135 | ||
136 | // jhlee HT 0 | |
137 | // CWYang(+) | |
138 | ||
139 | if ((HTType == 1) && ( zfRxBufferEqualToStr(dev, buf, oui11n, offset+2, 3) )) | |
140 | { | |
141 | if ( zmw_rx_buf_readb(dev, buf, offset+5) == HTEid ) | |
142 | { | |
143 | return offset + 5; | |
144 | } | |
145 | } | |
146 | ||
147 | } | |
148 | else | |
149 | { | |
150 | return offset; | |
151 | } | |
152 | } | |
153 | /* Advance to next element */ | |
154 | #if 1 | |
155 | elen = zmw_rx_buf_readb(dev, buf, offset+1); | |
156 | #else | |
92363b52 JP |
157 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
158 | if (elen == 0) | |
4bd43f50 LR |
159 | { |
160 | return 0xffff; | |
161 | } | |
162 | #endif | |
163 | ||
164 | offset += (elen+2); | |
165 | } | |
166 | return 0xffff; | |
167 | } | |
168 | ||
169 | ||
170 | /************************************************************************/ | |
171 | /* */ | |
172 | /* FUNCTION DESCRIPTION zfFindWifiElement */ | |
173 | /* Find a specific Wifi element in management frame */ | |
174 | /* */ | |
175 | /* INPUTS */ | |
176 | /* dev : device pointer */ | |
177 | /* buf : management frame buffer */ | |
178 | /* type : OUI type */ | |
179 | /* subType : OUI subtype */ | |
180 | /* */ | |
181 | /* OUTPUTS */ | |
182 | /* byte offset of target element */ | |
183 | /* or 0xffff if not found */ | |
184 | /* */ | |
185 | /* AUTHOR */ | |
186 | /* Stephen Chen ZyDAS Technology Corporation 2006.1 */ | |
187 | /* */ | |
188 | /************************************************************************/ | |
189 | u16_t zfFindWifiElement(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype) | |
190 | { | |
191 | u8_t subType; | |
192 | u16_t offset; | |
193 | u16_t bufLen; | |
194 | u16_t elen; | |
195 | u8_t id; | |
196 | u8_t tmp; | |
197 | ||
198 | /* Get offset of first element */ | |
199 | subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4); | |
200 | ||
92363b52 JP |
201 | offset = zgElementOffsetTable[subType]; |
202 | if (offset == 0xff) | |
4bd43f50 LR |
203 | { |
204 | zm_assert(0); | |
205 | } | |
206 | ||
207 | /* Plus wlan header */ | |
208 | offset += 24; | |
209 | ||
210 | bufLen = zfwBufGetSize(dev, buf); | |
211 | /* Search loop */ | |
212 | while ((offset+2)<bufLen) // including element ID and length (2bytes) | |
213 | { | |
214 | /* Search target element */ | |
92363b52 JP |
215 | id = zmw_rx_buf_readb(dev, buf, offset); |
216 | if (id == ZM_WLAN_EID_WIFI_IE) | |
4bd43f50 LR |
217 | { |
218 | /* Bingo */ | |
92363b52 JP |
219 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
220 | if (elen > bufLen - offset) | |
4bd43f50 LR |
221 | { |
222 | /* Element length error */ | |
223 | return 0xffff; | |
224 | } | |
225 | ||
226 | if ( elen == 0 ) | |
227 | { | |
228 | return 0xffff; | |
229 | } | |
230 | ||
231 | if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00) | |
232 | && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50) | |
233 | && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0xF2) | |
234 | && ((tmp = zmw_rx_buf_readb(dev, buf, offset+5)) == type)) | |
235 | ||
236 | { | |
237 | if ( subtype != 0xff ) | |
238 | { | |
92363b52 JP |
239 | tmp = zmw_rx_buf_readb(dev, buf, offset+6); |
240 | if (tmp == subtype) | |
4bd43f50 LR |
241 | { |
242 | return offset; | |
243 | } | |
244 | } | |
245 | else | |
246 | { | |
247 | return offset; | |
248 | } | |
249 | } | |
250 | } | |
251 | /* Advance to next element */ | |
92363b52 JP |
252 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
253 | if (elen == 0) | |
4bd43f50 LR |
254 | { |
255 | return 0xffff; | |
256 | } | |
257 | offset += (elen+2); | |
258 | } | |
259 | return 0xffff; | |
260 | } | |
261 | ||
262 | u16_t zfRemoveElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t eid) | |
263 | { | |
264 | u16_t offset = 0; | |
265 | u16_t elen; | |
266 | u8_t HTEid = 0; | |
267 | u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01}; | |
268 | u8_t oui11n[3] = {0x00,0x90,0x4C}; | |
269 | u8_t HTType = 0; | |
270 | ||
271 | if ((eid == ZM_WLAN_EID_HT_CAPABILITY) || | |
272 | (eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) | |
273 | { | |
274 | HTEid = eid; | |
275 | eid = ZM_WLAN_EID_WPA_IE; | |
276 | HTType = 1; | |
277 | } | |
278 | ||
279 | while (offset < size) | |
280 | { | |
281 | elen = *(buf+offset+1); | |
282 | ||
283 | if (*(buf+offset) == eid) | |
284 | { | |
285 | if ( eid == ZM_WLAN_EID_WPA_IE ) | |
286 | { | |
287 | if ( (HTType == 0) | |
288 | && (*(buf+offset+2) == oui[0]) | |
289 | && (*(buf+offset+3) == oui[1]) | |
290 | && (*(buf+offset+4) == oui[2]) | |
291 | && (*(buf+offset+5) == oui[3]) ) | |
292 | { | |
293 | zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2); | |
294 | return (size-elen-2); | |
295 | } | |
296 | ||
297 | if ( (HTType == 1) | |
298 | && (*(buf+offset+2) == oui11n[0]) | |
299 | && (*(buf+offset+3) == oui11n[1]) | |
300 | && (*(buf+offset+4) == oui11n[2]) | |
301 | && (*(buf+offset+5) == HTEid) ) | |
302 | { | |
303 | zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2); | |
304 | return (size-elen-2); | |
305 | } | |
306 | } | |
307 | else | |
308 | { | |
309 | zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2); | |
310 | return (size-elen-2); | |
311 | } | |
312 | } | |
313 | ||
314 | offset += (elen+2); | |
315 | } | |
316 | ||
317 | return size; | |
318 | } | |
319 | ||
320 | u16_t zfUpdateElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t* updateeid) | |
321 | { | |
322 | u16_t offset = 0; | |
323 | u16_t elen; | |
324 | ||
325 | while (offset < size) { | |
326 | elen = *(buf+offset+1); | |
327 | ||
328 | if (*(buf+offset) == updateeid[0]) { | |
329 | if (updateeid[1] <= elen) { | |
330 | zfMemoryMove(buf+offset, updateeid, updateeid[1]+2); | |
331 | zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2); | |
332 | ||
333 | return size-(elen-updateeid[1]); | |
334 | } else { | |
335 | zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2); | |
336 | zfMemoryMove(buf+offset, updateeid, updateeid[1]+2); | |
337 | ||
338 | return size+(updateeid[1]-elen); | |
339 | } | |
340 | } | |
341 | ||
342 | offset += (elen+2); | |
343 | } | |
344 | ||
345 | return size; | |
346 | } | |
347 | ||
348 | u16_t zfFindSuperGElement(zdev_t* dev, zbuf_t* buf, u8_t type) | |
349 | { | |
350 | u8_t subType; | |
351 | u16_t offset; | |
352 | u16_t bufLen; | |
353 | u16_t elen; | |
354 | u8_t id; | |
355 | u8_t super_feature; | |
356 | u8_t ouiSuperG[6] = {0x00,0x03,0x7f,0x01, 0x01, 0x00}; | |
357 | ||
4bd43f50 LR |
358 | /* Get offset of first element */ |
359 | subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4); | |
92363b52 JP |
360 | offset = zgElementOffsetTable[subType]; |
361 | if (offset == 0xff) | |
4bd43f50 LR |
362 | { |
363 | zm_assert(0); | |
364 | } | |
365 | ||
366 | /* Plus wlan header */ | |
367 | offset += 24; | |
368 | ||
369 | bufLen = zfwBufGetSize(dev, buf); | |
370 | /* Search loop */ | |
371 | while ((offset+2)<bufLen) // including element ID and length (2bytes) | |
372 | { | |
373 | /* Search target element */ | |
92363b52 JP |
374 | id = zmw_rx_buf_readb(dev, buf, offset); |
375 | if (id == ZM_WLAN_EID_VENDOR_PRIVATE) | |
4bd43f50 LR |
376 | { |
377 | /* Bingo */ | |
92363b52 JP |
378 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
379 | if (elen > bufLen - offset) | |
4bd43f50 LR |
380 | { |
381 | /* Element length error */ | |
382 | return 0xffff; | |
383 | } | |
384 | ||
385 | if ( elen == 0 ) | |
386 | { | |
387 | return 0xffff; | |
388 | } | |
389 | ||
390 | if (zfRxBufferEqualToStr(dev, buf, ouiSuperG, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6)) | |
391 | { | |
392 | /* super_feature 0:useFastFrame, 1:useCompression, 2:useTurboPrime */ | |
393 | super_feature= zmw_rx_buf_readb(dev, buf, offset+8); | |
394 | if ((super_feature & 0x01) || (super_feature & 0x02) || (super_feature & 0x04)) | |
395 | { | |
396 | return offset; | |
397 | } | |
398 | } | |
399 | } | |
400 | /* Advance to next element */ | |
401 | #if 1 | |
402 | elen = zmw_rx_buf_readb(dev, buf, offset+1); | |
403 | #else | |
92363b52 JP |
404 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
405 | if (elen == 0) | |
4bd43f50 LR |
406 | { |
407 | return 0xffff; | |
408 | } | |
409 | #endif | |
410 | ||
411 | offset += (elen+2); | |
412 | } | |
413 | return 0xffff; | |
414 | } | |
415 | ||
416 | u16_t zfFindXRElement(zdev_t* dev, zbuf_t* buf, u8_t type) | |
417 | { | |
418 | u8_t subType; | |
419 | u16_t offset; | |
420 | u16_t bufLen; | |
421 | u16_t elen; | |
422 | u8_t id; | |
423 | u8_t ouixr[6] = {0x00,0x03,0x7f,0x03, 0x01, 0x00}; | |
424 | ||
4bd43f50 LR |
425 | /* Get offset of first element */ |
426 | subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4); | |
92363b52 JP |
427 | offset = zgElementOffsetTable[subType]; |
428 | if (offset == 0xff) | |
4bd43f50 LR |
429 | { |
430 | zm_assert(0); | |
431 | } | |
432 | ||
433 | /* Plus wlan header */ | |
434 | offset += 24; | |
435 | ||
436 | bufLen = zfwBufGetSize(dev, buf); | |
437 | /* Search loop */ | |
438 | while ((offset+2)<bufLen) // including element ID and length (2bytes) | |
439 | { | |
440 | /* Search target element */ | |
92363b52 JP |
441 | id = zmw_rx_buf_readb(dev, buf, offset); |
442 | if (id == ZM_WLAN_EID_VENDOR_PRIVATE) | |
4bd43f50 LR |
443 | { |
444 | /* Bingo */ | |
92363b52 JP |
445 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
446 | if (elen > bufLen - offset) | |
4bd43f50 LR |
447 | { |
448 | /* Element length error */ | |
449 | return 0xffff; | |
450 | } | |
451 | ||
452 | if ( elen == 0 ) | |
453 | { | |
454 | return 0xffff; | |
455 | } | |
456 | ||
457 | if (zfRxBufferEqualToStr(dev, buf, ouixr, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6)) | |
458 | { | |
459 | return offset; | |
460 | } | |
461 | } | |
462 | /* Advance to next element */ | |
463 | #if 1 | |
464 | elen = zmw_rx_buf_readb(dev, buf, offset+1); | |
465 | #else | |
92363b52 JP |
466 | elen = zmw_rx_buf_readb(dev, buf, offset+1); |
467 | if (elen == 0) | |
4bd43f50 LR |
468 | { |
469 | return 0xffff; | |
470 | } | |
471 | #endif | |
472 | ||
473 | offset += (elen+2); | |
474 | } | |
475 | return 0xffff; | |
476 | } | |
477 | ||
478 | /************************************************************************/ | |
479 | /* */ | |
480 | /* FUNCTION DESCRIPTION zfMmAddIeSupportRate */ | |
481 | /* Add information element Support Rate to buffer. */ | |
482 | /* */ | |
483 | /* INPUTS */ | |
484 | /* dev : device pointer */ | |
485 | /* buf : buffer to add information element */ | |
486 | /* offset : add information element from this offset */ | |
487 | /* eid : element ID */ | |
488 | /* rateSet : CCK or OFDM */ | |
489 | /* */ | |
490 | /* OUTPUTS */ | |
491 | /* buffer offset after adding information element */ | |
492 | /* */ | |
493 | /* AUTHOR */ | |
494 | /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ | |
495 | /* */ | |
496 | /************************************************************************/ | |
497 | u16_t zfMmAddIeSupportRate(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t eid, u8_t rateSet) | |
498 | { | |
499 | u8_t len = 0; | |
500 | u16_t i; | |
501 | ||
502 | zmw_get_wlan_dev(dev); | |
503 | ||
504 | //if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) ) | |
505 | //{ | |
506 | // return offset; | |
507 | //} | |
508 | ||
509 | /* Information : Support Rate */ | |
510 | if ( rateSet == ZM_RATE_SET_CCK ) | |
511 | { | |
512 | for (i=0; i<4; i++) | |
513 | { | |
514 | if ((wd->bRate & (0x1<<i)) == (0x1<<i)) | |
515 | //if ((0xf & (0x1<<i)) == (0x1<<i)) | |
516 | { | |
517 | zmw_tx_buf_writeb(dev, buf, offset+len+2, | |
518 | zg11bRateTbl[i]+((wd->bRateBasic & (0x1<<i))<<(7-i))); | |
519 | len++; | |
520 | } | |
521 | } | |
522 | } | |
523 | else if ( rateSet == ZM_RATE_SET_OFDM ) | |
524 | { | |
525 | for (i=0; i<8; i++) | |
526 | { | |
527 | if ((wd->gRate & (0x1<<i)) == (0x1<<i)) | |
528 | //if ((0xff & (0x1<<i)) == (0x1<<i)) | |
529 | { | |
530 | zmw_tx_buf_writeb(dev, buf, offset+len+2, | |
531 | zg11gRateTbl[i]+((wd->gRateBasic & (0x1<<i))<<(7-i))); | |
532 | len++; | |
533 | } | |
534 | } | |
535 | } | |
536 | ||
537 | if (len > 0) | |
538 | { | |
539 | /* Element ID */ | |
540 | zmw_tx_buf_writeb(dev, buf, offset, eid); | |
541 | ||
542 | /* Element Length */ | |
543 | zmw_tx_buf_writeb(dev, buf, offset+1, len); | |
544 | ||
545 | /* Return value */ | |
546 | offset += (2+len); | |
547 | } | |
548 | ||
549 | return offset; | |
550 | } | |
551 | ||
552 | /************************************************************************/ | |
553 | /* */ | |
554 | /* FUNCTION DESCRIPTION zfMmAddIeDs */ | |
555 | /* Add information element DS to buffer. */ | |
556 | /* */ | |
557 | /* INPUTS */ | |
558 | /* dev : device pointer */ | |
559 | /* buf : buffer to add information element */ | |
560 | /* offset : add information element from this offset */ | |
561 | /* */ | |
562 | /* OUTPUTS */ | |
563 | /* buffer offset after adding information element */ | |
564 | /* */ | |
565 | /* AUTHOR */ | |
566 | /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ | |
567 | /* */ | |
568 | /************************************************************************/ | |
569 | u16_t zfMmAddIeDs(zdev_t* dev, zbuf_t* buf, u16_t offset) | |
570 | { | |
571 | zmw_get_wlan_dev(dev); | |
572 | ||
573 | /* Element ID */ | |
574 | zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_DS); | |
575 | ||
576 | /* Element Length */ | |
577 | zmw_tx_buf_writeb(dev, buf, offset++, 1); | |
578 | ||
579 | /* Information : DS */ | |
580 | zmw_tx_buf_writeb(dev, buf, offset++, | |
581 | zfChFreqToNum(wd->frequency, NULL)); | |
582 | ||
583 | return offset; | |
584 | } | |
585 | ||
586 | ||
587 | /************************************************************************/ | |
588 | /* */ | |
589 | /* FUNCTION DESCRIPTION zfMmAddIeErp */ | |
590 | /* Add information element ERP to buffer. */ | |
591 | /* */ | |
592 | /* INPUTS */ | |
593 | /* dev : device pointer */ | |
594 | /* buf : buffer to add information element */ | |
595 | /* offset : add information element from this offset */ | |
596 | /* */ | |
597 | /* OUTPUTS */ | |
598 | /* buffer offset after adding information element */ | |
599 | /* */ | |
600 | /* AUTHOR */ | |
601 | /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ | |
602 | /* */ | |
603 | /************************************************************************/ | |
604 | u16_t zfMmAddIeErp(zdev_t* dev, zbuf_t* buf, u16_t offset) | |
605 | { | |
606 | zmw_get_wlan_dev(dev); | |
607 | ||
608 | /* Element ID */ | |
609 | zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_ERP); | |
610 | ||
611 | /* Element Length */ | |
612 | zmw_tx_buf_writeb(dev, buf, offset++, 1); | |
613 | ||
614 | /* Information : ERP */ | |
615 | zmw_tx_buf_writeb(dev, buf, offset++, wd->erpElement); | |
616 | ||
617 | return offset; | |
618 | } | |
619 | ||
620 | ||
621 | /************************************************************************/ | |
622 | /* */ | |
623 | /* FUNCTION DESCRIPTION zfMmAddIeWpa */ | |
624 | /* Add information element WPA to buffer. */ | |
625 | /* */ | |
626 | /* INPUTS */ | |
627 | /* dev : device pointer */ | |
628 | /* buf : buffer to add information element */ | |
629 | /* offset : add information element from this offset */ | |
630 | /* */ | |
631 | /* OUTPUTS */ | |
632 | /* buffer offset after adding information element */ | |
633 | /* */ | |
634 | /* AUTHOR */ | |
635 | /* Yuan-Gu Wei ZyDAS Technology Corporation 2006.2 */ | |
636 | /* */ | |
637 | /************************************************************************/ | |
638 | u16_t zfMmAddIeWpa(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t apId) | |
639 | { | |
640 | //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev); | |
641 | int i; | |
642 | ||
643 | zmw_get_wlan_dev(dev); | |
644 | ||
645 | /* Element ID */ | |
646 | //zmw_inttx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE); | |
647 | ||
648 | /* Element Length */ | |
649 | //zmw_inttx_buf_writeb(dev, buf, offset++, wd->ap.wpaLen); | |
650 | for(i = 0; i < wd->ap.wpaLen[apId]; i++) | |
651 | { | |
652 | /* Information : WPA */ | |
653 | zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.wpaIe[apId][i]); | |
654 | } | |
655 | ||
656 | return offset; | |
657 | } | |
658 | ||
659 | /************************************************************************/ | |
660 | /* */ | |
661 | /* FUNCTION DESCRIPTION zfMmAddHTCapability */ | |
662 | /* Add HT Capability Infomation to buffer. */ | |
663 | /* */ | |
664 | /* INPUTS */ | |
665 | /* dev : device pointer */ | |
666 | /* buf : buffer to add information element */ | |
667 | /* offset : add information element from this offset */ | |
668 | /* */ | |
669 | /* OUTPUTS */ | |
670 | /* buffer offset after adding information element */ | |
671 | /* */ | |
672 | /* AUTHOR */ | |
673 | /* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */ | |
674 | /* */ | |
675 | /************************************************************************/ | |
676 | u16_t zfMmAddHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset) | |
677 | { | |
678 | u8_t OUI[3] = {0x0,0x90,0x4C}; | |
679 | u16_t i; | |
680 | ||
681 | zmw_get_wlan_dev(dev); | |
682 | ||
683 | /* Prob ID */ | |
684 | zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE); | |
685 | ||
686 | if ( wd->wlanMode == ZM_MODE_AP ) | |
687 | { | |
688 | /* Element Length */ | |
689 | zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length + 4); | |
690 | ||
691 | /* OUI Data */ | |
692 | for (i = 0; i < 3; i++) | |
693 | { | |
694 | zmw_buf_writeb(dev, buf, offset++, OUI[i]); | |
695 | } | |
696 | ||
697 | /* Element Type ID */ | |
698 | zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.ElementID); | |
699 | ||
700 | /* HT Capability Data */ | |
701 | for (i = 0; i < 26; i++) | |
702 | { | |
703 | zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]); | |
704 | } | |
705 | } | |
706 | else | |
707 | { | |
708 | /* Element Length */ | |
709 | zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length + 4); | |
710 | ||
711 | /* OUI Data */ | |
712 | for (i = 0; i < 3; i++) | |
713 | { | |
714 | zmw_buf_writeb(dev, buf, offset++, OUI[i]); | |
715 | } | |
716 | ||
717 | /* Element Type ID */ | |
718 | zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.ElementID); | |
719 | ||
720 | /* HT Capability Data */ | |
721 | for (i = 0; i < 26; i++) | |
722 | { | |
723 | zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]); | |
724 | } | |
725 | } | |
726 | ||
727 | return offset; | |
728 | } | |
729 | ||
730 | ||
731 | u16_t zfMmAddPreNHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset) | |
732 | { | |
733 | //u8_t OUI[3] = {0x0,0x90,0x4C}; | |
734 | u16_t i; | |
735 | ||
736 | zmw_get_wlan_dev(dev); | |
737 | ||
738 | /* Prob ID */ | |
739 | zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_PREN2_EID_HTCAPABILITY); | |
740 | ||
741 | if ( wd->wlanMode == ZM_MODE_AP ) | |
742 | { | |
743 | /* Element Length */ | |
744 | zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length); | |
745 | ||
746 | /* HT Capability Data */ | |
747 | for (i = 0; i < 26; i++) | |
748 | { | |
749 | zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]); | |
750 | } | |
751 | } | |
752 | else | |
753 | { | |
754 | /* Element Length */ | |
755 | zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length); | |
756 | ||
757 | /* HT Capability Data */ | |
758 | for (i = 0; i < 26; i++) | |
759 | { | |
760 | zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]); | |
761 | } | |
762 | } | |
763 | ||
764 | return offset; | |
765 | } | |
766 | ||
767 | /************************************************************************/ | |
768 | /* */ | |
769 | /* FUNCTION DESCRIPTION zfMmAddExtendedHTCapability */ | |
770 | /* Add Extended HT Capability Infomation to buffer. */ | |
771 | /* */ | |
772 | /* INPUTS */ | |
773 | /* dev : device pointer */ | |
774 | /* buf : buffer to add information element */ | |
775 | /* offset : add information element from this offset */ | |
776 | /* */ | |
777 | /* OUTPUTS */ | |
778 | /* buffer offset after adding information element */ | |
779 | /* */ | |
780 | /* AUTHOR */ | |
781 | /* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */ | |
782 | /* */ | |
783 | /************************************************************************/ | |
784 | u16_t zfMmAddExtendedHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset) | |
785 | { | |
786 | u8_t OUI[3] = {0x0,0x90,0x4C}; | |
787 | u16_t i; | |
788 | ||
789 | zmw_get_wlan_dev(dev); | |
790 | ||
791 | /* Prob ID */ | |
792 | zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE); | |
793 | ||
794 | if ( wd->wlanMode == ZM_MODE_AP ) | |
795 | { | |
796 | /* Element Length */ | |
797 | zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.Length + 4); | |
798 | ||
799 | /* OUI Data */ | |
800 | for (i = 0; i < 3; i++) | |
801 | { | |
802 | zmw_buf_writeb(dev, buf, offset++, OUI[i]); | |
803 | } | |
804 | ||
805 | /* Element Type ID */ | |
806 | zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.ElementID); | |
807 | ||
808 | /* HT Capability Data */ | |
809 | for (i = 0; i < 22; i++) | |
810 | { | |
811 | zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Byte[i+2]); | |
812 | } | |
813 | } | |
814 | else | |
815 | { | |
816 | /* Element Length */ | |
817 | zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.Length + 4); | |
818 | ||
819 | /* OUI Data */ | |
820 | for (i = 0; i < 3; i++) | |
821 | { | |
822 | zmw_buf_writeb(dev, buf, offset++, OUI[i]); | |
823 | } | |
824 | ||
825 | /* Element Type ID */ | |
826 | zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.ElementID); | |
827 | ||
828 | /* HT Capability Data */ | |
829 | for (i = 0; i < 22; i++) | |
830 | { | |
831 | zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Byte[i+2]); | |
832 | } | |
833 | } | |
834 | ||
835 | return offset; | |
836 | } | |
837 | ||
838 | ||
839 | ||
840 | /************************************************************************/ | |
841 | /* */ | |
842 | /* FUNCTION DESCRIPTION zfSendMmFrame */ | |
843 | /* Send management frame. */ | |
844 | /* */ | |
845 | /* INPUTS */ | |
846 | /* dev : device pointer */ | |
847 | /* frameType : management frame type */ | |
848 | /* dst : destination MAC address */ | |
849 | /* p1 : parameter 1 */ | |
850 | /* p2 : parameter 2 */ | |
851 | /* p3 : parameter 3 */ | |
852 | /* */ | |
853 | /* OUTPUTS */ | |
854 | /* none */ | |
855 | /* */ | |
856 | /* AUTHOR */ | |
857 | /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ | |
858 | /* */ | |
859 | /************************************************************************/ | |
860 | /* probe req : p1=> bWithSSID, p2=>R, p3=>R */ | |
861 | /* probe rsp : p1=>R, p2=>R, p3=>VAP ID(AP) */ | |
862 | /* deauth : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */ | |
863 | /* Disasoc : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */ | |
864 | /* ATIM : p1=>R, p2=>R, p3=>R */ | |
865 | /* (re)asoc rsp : p1=>Status Code, p2=>AID, p3=>VAP ID(AP) */ | |
866 | /* asoc req : p1=>R, p2=>R, p3=>R */ | |
867 | /* reasoc req : p1=>AP MAC[0], p2=>AP MAC[1], p3=>AP MAC[2] */ | |
868 | /* auth : p1=>low=Algorithm, high=Transaction, p2=>Status, p3=>VAP ID */ | |
869 | void zfSendMmFrame(zdev_t* dev, u8_t frameType, u16_t* dst, | |
870 | u32_t p1, u32_t p2, u32_t p3) | |
871 | { | |
872 | zbuf_t* buf; | |
873 | //u16_t addrTblSize; | |
874 | //struct zsAddrTbl addrTbl; | |
875 | u16_t offset = 0; | |
876 | u16_t hlen = 32; | |
877 | u16_t header[(24+25+1)/2]; | |
878 | u16_t vap = 0; | |
879 | u16_t i; | |
880 | u8_t encrypt = 0; | |
881 | u16_t aid; | |
882 | ||
883 | zmw_get_wlan_dev(dev); | |
884 | zmw_declare_for_critical_section(); | |
885 | ||
886 | zm_msg2_mm(ZM_LV_2, "Send mm frame, type=", frameType); | |
658ce9d6 | 887 | /* TBD : Maximum size of management frame */ |
92363b52 JP |
888 | buf = zfwBufAllocate(dev, 1024); |
889 | if (buf == NULL) | |
4bd43f50 LR |
890 | { |
891 | zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!"); | |
892 | return; | |
893 | } | |
894 | ||
895 | //Reserve room for wlan header | |
896 | offset = hlen; | |
897 | ||
898 | switch (frameType) | |
899 | { | |
900 | case ZM_WLAN_FRAME_TYPE_PROBEREQ : | |
901 | offset = zfSendProbeReq(dev, buf, offset, (u8_t) p1); | |
902 | break; | |
903 | ||
904 | case ZM_WLAN_FRAME_TYPE_PROBERSP : | |
905 | zm_msg0_mm(ZM_LV_3, "probe rsp"); | |
906 | /* 24-31 Time Stamp : hardware WON'T fill this field */ | |
907 | zmw_tx_buf_writeh(dev, buf, offset, 0); | |
908 | zmw_tx_buf_writeh(dev, buf, offset+2, 0); | |
909 | zmw_tx_buf_writeh(dev, buf, offset+4, 0); | |
910 | zmw_tx_buf_writeh(dev, buf, offset+6, 0); | |
911 | offset+=8; | |
912 | ||
913 | /* Beacon Interval */ | |
914 | zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval); | |
915 | offset+=2; | |
916 | ||
917 | if (wd->wlanMode == ZM_MODE_AP) | |
918 | { | |
919 | vap = (u16_t) p3; | |
920 | /* Capability */ | |
921 | zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]); | |
922 | offset+=2; | |
923 | /* SSID */ | |
924 | offset = zfApAddIeSsid(dev, buf, offset, vap); | |
925 | } | |
926 | else | |
927 | { | |
928 | /* Capability */ | |
929 | zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]); | |
930 | zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]); | |
931 | /* SSID */ | |
932 | offset = zfStaAddIeSsid(dev, buf, offset); | |
933 | } | |
934 | ||
935 | /* Support Rate */ | |
936 | if ( wd->frequency < 3000 ) | |
937 | { | |
938 | offset = zfMmAddIeSupportRate(dev, buf, offset, | |
939 | ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK); | |
940 | } | |
941 | else | |
942 | { | |
943 | offset = zfMmAddIeSupportRate(dev, buf, offset, | |
944 | ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM); | |
945 | } | |
946 | ||
947 | /* DS parameter set */ | |
948 | offset = zfMmAddIeDs(dev, buf, offset); | |
949 | ||
950 |