This source file includes following definitions.
- ieee80211_ifattach
- ieee80211_ifdetach
- ieee80211_mhz2ieee
- ieee80211_chan2ieee
- ieee80211_ieee2mhz
- ieee80211_media_init
- ieee80211_findrate
- ieee80211_media_change
- ieee80211_media_status
- ieee80211_watchdog
- ieee80211_setbasicrates
- ieee80211_setmode
- ieee80211_next_mode
- ieee80211_chan2mode
- ieee80211_rate2media
- ieee80211_media2rate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include "bpfilter.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/sockio.h>
44 #include <sys/endian.h>
45 #include <sys/errno.h>
46 #include <sys/proc.h>
47 #include <sys/sysctl.h>
48
49 #include <net/if.h>
50 #include <net/if_dl.h>
51 #include <net/if_media.h>
52 #include <net/if_arp.h>
53 #include <net/if_llc.h>
54
55 #if NBPFILTER > 0
56 #include <net/bpf.h>
57 #endif
58
59 #ifdef INET
60 #include <netinet/in.h>
61 #include <netinet/if_ether.h>
62 #endif
63
64 #include <net80211/ieee80211_var.h>
65
66 #ifdef IEEE80211_DEBUG
67 int ieee80211_debug = 0;
68 #endif
69
70 int ieee80211_cache_size = IEEE80211_CACHE_SIZE;
71
72 struct ieee80211com_head ieee80211com_head =
73 LIST_HEAD_INITIALIZER(ieee80211com_head);
74
75 void ieee80211_setbasicrates(struct ieee80211com *);
76 int ieee80211_findrate(struct ieee80211com *, enum ieee80211_phymode, int);
77
78 void
79 ieee80211_ifattach(struct ifnet *ifp)
80 {
81 struct ieee80211com *ic = (void *)ifp;
82 struct ieee80211_channel *c;
83 int i;
84
85 memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
86 ETHER_ADDR_LEN);
87 ether_ifattach(ifp);
88
89 ifp->if_output = ieee80211_output;
90
91 #if NBPFILTER > 0
92 bpfattach(&ic->ic_rawbpf, ifp, DLT_IEEE802_11,
93 sizeof(struct ieee80211_frame_addr4));
94 #endif
95 ieee80211_crypto_attach(ifp);
96
97
98
99
100
101
102 memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
103 ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO;
104 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
105 c = &ic->ic_channels[i];
106 if (c->ic_flags) {
107
108
109
110 if (i != ieee80211_chan2ieee(ic, c)) {
111 printf("%s: bad channel ignored; "
112 "freq %u flags %x number %u\n",
113 ifp->if_xname, c->ic_freq, c->ic_flags,
114 i);
115 c->ic_flags = 0;
116 continue;
117 }
118 setbit(ic->ic_chan_avail, i);
119
120
121
122 if (IEEE80211_IS_CHAN_A(c))
123 ic->ic_modecaps |= 1<<IEEE80211_MODE_11A;
124 if (IEEE80211_IS_CHAN_B(c))
125 ic->ic_modecaps |= 1<<IEEE80211_MODE_11B;
126 if (IEEE80211_IS_CHAN_PUREG(c))
127 ic->ic_modecaps |= 1<<IEEE80211_MODE_11G;
128 if (IEEE80211_IS_CHAN_FHSS(c))
129 ic->ic_modecaps |= 1<<IEEE80211_MODE_FH;
130 if (IEEE80211_IS_CHAN_T(c))
131 ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO;
132 }
133 }
134
135 if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0)
136 ic->ic_curmode = IEEE80211_MODE_AUTO;
137 ic->ic_des_chan = IEEE80211_CHAN_ANYC;
138 ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
139
140
141 ifp->if_capabilities |= IFCAP_VLAN_MTU;
142
143 ieee80211_setbasicrates(ic);
144 (void) ieee80211_setmode(ic, ic->ic_curmode);
145
146 if (ic->ic_lintval == 0)
147 ic->ic_lintval = 100;
148 ic->ic_bmisstimeout = 7*ic->ic_lintval;
149 ic->ic_dtim_period = 1;
150
151 LIST_INSERT_HEAD(&ieee80211com_head, ic, ic_list);
152 ieee80211_node_attach(ifp);
153 ieee80211_proto_attach(ifp);
154
155 if_addgroup(ifp, "wlan");
156 }
157
158 void
159 ieee80211_ifdetach(struct ifnet *ifp)
160 {
161 struct ieee80211com *ic = (void *)ifp;
162
163 ieee80211_proto_detach(ifp);
164 ieee80211_crypto_detach(ifp);
165 ieee80211_node_detach(ifp);
166 LIST_REMOVE(ic, ic_list);
167 ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
168 ether_ifdetach(ifp);
169 }
170
171
172
173
174 u_int
175 ieee80211_mhz2ieee(u_int freq, u_int flags)
176 {
177 if (flags & IEEE80211_CHAN_2GHZ) {
178 if (freq == 2484)
179 return 14;
180 if (freq < 2484)
181 return (freq - 2407) / 5;
182 else
183 return 15 + ((freq - 2512) / 20);
184 } else if (flags & IEEE80211_CHAN_5GHZ) {
185 return (freq - 5000) / 5;
186 } else {
187 if (freq == 2484)
188 return 14;
189 if (freq < 2484)
190 return (freq - 2407) / 5;
191 if (freq < 5000)
192 return 15 + ((freq - 2512) / 20);
193 return (freq - 5000) / 5;
194 }
195 }
196
197
198
199
200 u_int
201 ieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c)
202 {
203 struct ifnet *ifp = &ic->ic_if;
204 if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX])
205 return c - ic->ic_channels;
206 else if (c == IEEE80211_CHAN_ANYC)
207 return IEEE80211_CHAN_ANY;
208 else if (c != NULL) {
209 printf("%s: invalid channel freq %u flags %x\n",
210 ifp->if_xname, c->ic_freq, c->ic_flags);
211 return 0;
212 } else {
213 printf("%s: invalid channel (NULL)\n", ifp->if_xname);
214 return 0;
215 }
216 }
217
218
219
220
221 u_int
222 ieee80211_ieee2mhz(u_int chan, u_int flags)
223 {
224 if (flags & IEEE80211_CHAN_2GHZ) {
225 if (chan == 14)
226 return 2484;
227 if (chan < 14)
228 return 2407 + chan*5;
229 else
230 return 2512 + ((chan-15)*20);
231 } else if (flags & IEEE80211_CHAN_5GHZ) {
232 return 5000 + (chan*5);
233 } else {
234 if (chan == 14)
235 return 2484;
236 if (chan < 14)
237 return 2407 + chan*5;
238 if (chan < 27)
239 return 2512 + ((chan-15)*20);
240 return 5000 + (chan*5);
241 }
242 }
243
244
245
246
247
248
249 void
250 ieee80211_media_init(struct ifnet *ifp,
251 ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
252 {
253 #define ADD(_ic, _s, _o) \
254 ifmedia_add(&(_ic)->ic_media, \
255 IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL)
256 struct ieee80211com *ic = (void *)ifp;
257 struct ifmediareq imr;
258 int i, j, mode, rate, maxrate, mword, mopt, r;
259 const struct ieee80211_rateset *rs;
260 struct ieee80211_rateset allrates;
261
262
263
264
265
266 ieee80211_node_lateattach(ifp);
267
268
269
270
271 ifmedia_init(&ic->ic_media, 0, media_change, media_stat);
272 maxrate = 0;
273 memset(&allrates, 0, sizeof(allrates));
274 for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) {
275 static const u_int mopts[] = {
276 IFM_AUTO,
277 IFM_IEEE80211_11A,
278 IFM_IEEE80211_11B,
279 IFM_IEEE80211_11G,
280 IFM_IEEE80211_FH,
281 IFM_IEEE80211_11A | IFM_IEEE80211_TURBO,
282 };
283 if ((ic->ic_modecaps & (1<<mode)) == 0)
284 continue;
285 mopt = mopts[mode];
286 ADD(ic, IFM_AUTO, mopt);
287 if (ic->ic_caps & IEEE80211_C_IBSS)
288 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS);
289 if (ic->ic_caps & IEEE80211_C_HOSTAP)
290 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP);
291 if (ic->ic_caps & IEEE80211_C_AHDEMO)
292 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC);
293 if (ic->ic_caps & IEEE80211_C_MONITOR)
294 ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR);
295 if (mode == IEEE80211_MODE_AUTO)
296 continue;
297 rs = &ic->ic_sup_rates[mode];
298 for (i = 0; i < rs->rs_nrates; i++) {
299 rate = rs->rs_rates[i];
300 mword = ieee80211_rate2media(ic, rate, mode);
301 if (mword == 0)
302 continue;
303 ADD(ic, mword, mopt);
304 if (ic->ic_caps & IEEE80211_C_IBSS)
305 ADD(ic, mword, mopt | IFM_IEEE80211_IBSS);
306 if (ic->ic_caps & IEEE80211_C_HOSTAP)
307 ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP);
308 if (ic->ic_caps & IEEE80211_C_AHDEMO)
309 ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC);
310 if (ic->ic_caps & IEEE80211_C_MONITOR)
311 ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR);
312
313
314
315 r = rate & IEEE80211_RATE_VAL;
316 for (j = 0; j < allrates.rs_nrates; j++)
317 if (allrates.rs_rates[j] == r)
318 break;
319 if (j == allrates.rs_nrates) {
320
321 allrates.rs_rates[j] = r;
322 allrates.rs_nrates++;
323 }
324 rate = (rate & IEEE80211_RATE_VAL) / 2;
325 if (rate > maxrate)
326 maxrate = rate;
327 }
328 }
329 for (i = 0; i < allrates.rs_nrates; i++) {
330 mword = ieee80211_rate2media(ic, allrates.rs_rates[i],
331 IEEE80211_MODE_AUTO);
332 if (mword == 0)
333 continue;
334 mword = IFM_SUBTYPE(mword);
335 ADD(ic, mword, 0);
336 if (ic->ic_caps & IEEE80211_C_IBSS)
337 ADD(ic, mword, IFM_IEEE80211_IBSS);
338 if (ic->ic_caps & IEEE80211_C_HOSTAP)
339 ADD(ic, mword, IFM_IEEE80211_HOSTAP);
340 if (ic->ic_caps & IEEE80211_C_AHDEMO)
341 ADD(ic, mword, IFM_IEEE80211_ADHOC);
342 if (ic->ic_caps & IEEE80211_C_MONITOR)
343 ADD(ic, mword, IFM_IEEE80211_MONITOR);
344 }
345 ieee80211_media_status(ifp, &imr);
346 ifmedia_set(&ic->ic_media, imr.ifm_active);
347
348 if (maxrate)
349 ifp->if_baudrate = IF_Mbps(maxrate);
350
351 #undef ADD
352 }
353
354 int
355 ieee80211_findrate(struct ieee80211com *ic, enum ieee80211_phymode mode,
356 int rate)
357 {
358 #define IEEERATE(_ic,_m,_i) \
359 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL)
360 int i, nrates = ic->ic_sup_rates[mode].rs_nrates;
361 for (i = 0; i < nrates; i++)
362 if (IEEERATE(ic, mode, i) == rate)
363 return i;
364 return -1;
365 #undef IEEERATE
366 }
367
368
369
370
371 int
372 ieee80211_media_change(struct ifnet *ifp)
373 {
374 struct ieee80211com *ic = (void *)ifp;
375 struct ifmedia_entry *ime;
376 enum ieee80211_opmode newopmode;
377 enum ieee80211_phymode newphymode;
378 int i, j, newrate, error = 0;
379
380 ime = ic->ic_media.ifm_cur;
381
382
383
384 switch (IFM_MODE(ime->ifm_media)) {
385 case IFM_IEEE80211_11A:
386 newphymode = IEEE80211_MODE_11A;
387 break;
388 case IFM_IEEE80211_11B:
389 newphymode = IEEE80211_MODE_11B;
390 break;
391 case IFM_IEEE80211_11G:
392 newphymode = IEEE80211_MODE_11G;
393 break;
394 case IFM_IEEE80211_FH:
395 newphymode = IEEE80211_MODE_FH;
396 break;
397 case IFM_AUTO:
398 newphymode = IEEE80211_MODE_AUTO;
399 break;
400 default:
401 return EINVAL;
402 }
403
404
405
406
407 if (ime->ifm_media & IFM_IEEE80211_TURBO) {
408 if (newphymode != IEEE80211_MODE_11A)
409 return EINVAL;
410 newphymode = IEEE80211_MODE_TURBO;
411 }
412
413
414
415 if ((ic->ic_modecaps & (1<<newphymode)) == 0)
416 return EINVAL;
417
418
419
420
421 i = -1;
422 if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) {
423
424
425
426 newrate = ieee80211_media2rate(ime->ifm_media);
427 if (newrate == 0)
428 return EINVAL;
429
430
431
432 if (newphymode == IEEE80211_MODE_AUTO) {
433
434
435
436 for (j = IEEE80211_MODE_11A;
437 j < IEEE80211_MODE_MAX; j++) {
438 if ((ic->ic_modecaps & (1<<j)) == 0)
439 continue;
440 i = ieee80211_findrate(ic, j, newrate);
441 if (i != -1) {
442
443 newphymode = j;
444 break;
445 }
446 }
447 } else {
448 i = ieee80211_findrate(ic, newphymode, newrate);
449 }
450 if (i == -1)
451 return EINVAL;
452 }
453
454
455
456
457
458 if (ime->ifm_media & IFM_IEEE80211_ADHOC)
459 newopmode = IEEE80211_M_AHDEMO;
460 else if (ime->ifm_media & IFM_IEEE80211_HOSTAP)
461 newopmode = IEEE80211_M_HOSTAP;
462 else if (ime->ifm_media & IFM_IEEE80211_IBSS)
463 newopmode = IEEE80211_M_IBSS;
464 else if (ime->ifm_media & IFM_IEEE80211_MONITOR)
465 newopmode = IEEE80211_M_MONITOR;
466 else
467 newopmode = IEEE80211_M_STA;
468
469
470
471
472
473
474
475 if (newopmode == IEEE80211_M_HOSTAP &&
476 newphymode == IEEE80211_MODE_AUTO) {
477 for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++)
478 if (ic->ic_modecaps & (1<<j)) {
479 newphymode = j;
480 break;
481 }
482 }
483
484
485
486
487 if (ic->ic_curmode != newphymode) {
488 error = ieee80211_setmode(ic, newphymode);
489 if (error != 0)
490 return error;
491 error = ENETRESET;
492 }
493
494
495
496
497 if (ic->ic_fixed_rate != i) {
498 ic->ic_fixed_rate = i;
499 error = ENETRESET;
500 }
501
502
503
504
505 if (ic->ic_opmode != newopmode) {
506 ic->ic_opmode = newopmode;
507 switch (newopmode) {
508 case IEEE80211_M_AHDEMO:
509 case IEEE80211_M_HOSTAP:
510 case IEEE80211_M_STA:
511 case IEEE80211_M_MONITOR:
512 ic->ic_flags &= ~IEEE80211_F_IBSSON;
513 break;
514 case IEEE80211_M_IBSS:
515 ic->ic_flags |= IEEE80211_F_IBSSON;
516 break;
517 }
518
519
520
521
522
523 ieee80211_reset_erp(ic);
524 error = ENETRESET;
525 }
526 #ifdef notdef
527 if (error == 0)
528 ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);
529 #endif
530 return error;
531 }
532
533 void
534 ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
535 {
536 struct ieee80211com *ic = (void *)ifp;
537 const struct ieee80211_node *ni = NULL;
538
539 imr->ifm_status = IFM_AVALID;
540 imr->ifm_active = IFM_IEEE80211;
541 if (ic->ic_state == IEEE80211_S_RUN)
542 imr->ifm_status |= IFM_ACTIVE;
543 imr->ifm_active |= IFM_AUTO;
544 switch (ic->ic_opmode) {
545 case IEEE80211_M_STA:
546 ni = ic->ic_bss;
547
548 imr->ifm_active |= ieee80211_rate2media(ic,
549 ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode);
550 break;
551 case IEEE80211_M_IBSS:
552 imr->ifm_active |= IFM_IEEE80211_IBSS;
553 break;
554 case IEEE80211_M_AHDEMO:
555 imr->ifm_active |= IFM_IEEE80211_ADHOC;
556 break;
557 case IEEE80211_M_HOSTAP:
558 imr->ifm_active |= IFM_IEEE80211_HOSTAP;
559 break;
560 case IEEE80211_M_MONITOR:
561 imr->ifm_active |= IFM_IEEE80211_MONITOR;
562 break;
563 }
564 switch (ic->ic_curmode) {
565 case IEEE80211_MODE_11A:
566 imr->ifm_active |= IFM_IEEE80211_11A;
567 break;
568 case IEEE80211_MODE_11B:
569 imr->ifm_active |= IFM_IEEE80211_11B;
570 break;
571 case IEEE80211_MODE_11G:
572 imr->ifm_active |= IFM_IEEE80211_11G;
573 break;
574 case IEEE80211_MODE_FH:
575 imr->ifm_active |= IFM_IEEE80211_FH;
576 break;
577 case IEEE80211_MODE_TURBO:
578 imr->ifm_active |= IFM_IEEE80211_11A
579 | IFM_IEEE80211_TURBO;
580 break;
581 }
582 }
583
584 void
585 ieee80211_watchdog(struct ifnet *ifp)
586 {
587 struct ieee80211com *ic = (void *)ifp;
588
589 if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0)
590 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
591
592 if (ic->ic_mgt_timer != 0)
593 ifp->if_timer = 1;
594 }
595
596 const struct ieee80211_rateset ieee80211_std_rateset_11a =
597 { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
598
599 const struct ieee80211_rateset ieee80211_std_rateset_11b =
600 { 4, { 2, 4, 11, 22 } };
601
602 const struct ieee80211_rateset ieee80211_std_rateset_11g =
603 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
604
605
606
607
608
609
610
611
612 void
613 ieee80211_setbasicrates(struct ieee80211com *ic)
614 {
615 static const struct ieee80211_rateset basic[] = {
616 { 0 },
617 { 3, { 12, 24, 48 } },
618 { 2, { 2, 4 } },
619 { 4, { 2, 4, 11, 22 } },
620 { 2, { 2, 4 } },
621 { 0 },
622 };
623 enum ieee80211_phymode mode;
624 struct ieee80211_rateset *rs;
625 int i, j;
626
627 for (mode = 0; mode < IEEE80211_MODE_MAX; mode++) {
628 rs = &ic->ic_sup_rates[mode];
629 for (i = 0; i < rs->rs_nrates; i++) {
630 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
631 for (j = 0; j < basic[mode].rs_nrates; j++) {
632 if (basic[mode].rs_rates[j] ==
633 rs->rs_rates[i]) {
634 rs->rs_rates[i] |=
635 IEEE80211_RATE_BASIC;
636 break;
637 }
638 }
639 }
640 }
641 }
642
643
644
645
646
647
648
649 int
650 ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
651 {
652 #define N(a) (sizeof(a) / sizeof(a[0]))
653 struct ifnet *ifp = &ic->ic_if;
654 static const u_int chanflags[] = {
655 0,
656 IEEE80211_CHAN_A,
657 IEEE80211_CHAN_B,
658 IEEE80211_CHAN_PUREG,
659 IEEE80211_CHAN_FHSS,
660 IEEE80211_CHAN_T,
661 };
662 const struct ieee80211_channel *c;
663 u_int modeflags;
664 int i;
665
666
667 if ((ic->ic_modecaps & (1<<mode)) == 0) {
668 IEEE80211_DPRINTF(("%s: mode %u not supported (caps 0x%x)\n",
669 __func__, mode, ic->ic_modecaps));
670 return EINVAL;
671 }
672
673
674
675
676
677 if (mode >= N(chanflags))
678 panic("Unexpected mode %u", mode);
679 modeflags = chanflags[mode];
680 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
681 c = &ic->ic_channels[i];
682 if (mode == IEEE80211_MODE_AUTO) {
683
684 if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
685 break;
686 } else {
687 if ((c->ic_flags & modeflags) == modeflags)
688 break;
689 }
690 }
691 if (i > IEEE80211_CHAN_MAX) {
692 IEEE80211_DPRINTF(("%s: no channels found for mode %u\n",
693 __func__, mode));
694 return EINVAL;
695 }
696
697
698
699
700 memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active));
701 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
702 c = &ic->ic_channels[i];
703 if (mode == IEEE80211_MODE_AUTO) {
704
705 if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0)
706 setbit(ic->ic_chan_active, i);
707 } else {
708 if ((c->ic_flags & modeflags) == modeflags)
709 setbit(ic->ic_chan_active, i);
710 }
711 }
712
713
714
715
716
717
718 if (ic->ic_ibss_chan == NULL || isclr(ic->ic_chan_active,
719 ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) {
720 for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
721 if (isset(ic->ic_chan_active, i)) {
722 ic->ic_ibss_chan = &ic->ic_channels[i];
723 break;
724 }
725 if ((ic->ic_ibss_chan == NULL) || isclr(ic->ic_chan_active,
726 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)))
727 panic("Bad IBSS channel %u\n",
728 ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
729 }
730
731
732
733
734
735 ieee80211_reset_scan(ifp);
736
737 ic->ic_curmode = mode;
738 ieee80211_reset_erp(ic);
739
740 return 0;
741 #undef N
742 }
743
744 enum ieee80211_phymode
745 ieee80211_next_mode(struct ifnet *ifp)
746 {
747 struct ieee80211com *ic = (void *)ifp;
748
749 if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) != IFM_AUTO) {
750
751
752
753
754 ieee80211_reset_scan(ifp);
755 return (IEEE80211_MODE_AUTO);
756 }
757
758
759
760
761 for (++ic->ic_curmode;
762 ic->ic_curmode <= IEEE80211_MODE_TURBO;
763 ic->ic_curmode++) {
764
765 if (ic->ic_curmode >= IEEE80211_MODE_TURBO) {
766 ic->ic_curmode = IEEE80211_MODE_AUTO;
767 break;
768 }
769
770 if (ic->ic_modecaps & (1 << ic->ic_curmode))
771 break;
772 }
773
774 ieee80211_setmode(ic, ic->ic_curmode);
775
776 return (ic->ic_curmode);
777 }
778
779
780
781
782
783
784
785
786 enum ieee80211_phymode
787 ieee80211_chan2mode(struct ieee80211com *ic,
788 const struct ieee80211_channel *chan)
789 {
790
791
792
793
794 if (ic->ic_curmode != IEEE80211_MODE_AUTO ||
795 chan == IEEE80211_CHAN_ANYC)
796 return ic->ic_curmode;
797
798
799
800
801
802 if (IEEE80211_IS_CHAN_T(chan))
803 return IEEE80211_MODE_TURBO;
804 else if (IEEE80211_IS_CHAN_5GHZ(chan))
805 return IEEE80211_MODE_11A;
806 else if (IEEE80211_IS_CHAN_FHSS(chan))
807 return IEEE80211_MODE_FH;
808 else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN))
809 return IEEE80211_MODE_11G;
810 else
811 return IEEE80211_MODE_11B;
812 }
813
814
815
816
817
818 int
819 ieee80211_rate2media(struct ieee80211com *ic, int rate,
820 enum ieee80211_phymode mode)
821 {
822 #define N(a) (sizeof(a) / sizeof(a[0]))
823 static const struct {
824 u_int m;
825 u_int r;
826 } rates[] = {
827 { 2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 },
828 { 4 | IFM_IEEE80211_FH, IFM_IEEE80211_FH2 },
829 { 2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 },
830 { 4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 },
831 { 11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 },
832 { 22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 },
833 { 44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 },
834 { 12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 },
835 { 18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 },
836 { 24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 },
837 { 36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 },
838 { 48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 },
839 { 72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 },
840 { 96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 },
841 { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 },
842 { 2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 },
843 { 4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 },
844 { 11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 },
845 { 22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 },
846 { 12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 },
847 { 18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 },
848 { 24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 },
849 { 36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 },
850 { 48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 },
851 { 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 },
852 { 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 },
853 { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 },
854
855 };
856 u_int mask, i;
857
858 mask = rate & IEEE80211_RATE_VAL;
859 switch (mode) {
860 case IEEE80211_MODE_11A:
861 case IEEE80211_MODE_TURBO:
862 mask |= IFM_IEEE80211_11A;
863 break;
864 case IEEE80211_MODE_11B:
865 mask |= IFM_IEEE80211_11B;
866 break;
867 case IEEE80211_MODE_FH:
868 mask |= IFM_IEEE80211_FH;
869 break;
870 case IEEE80211_MODE_AUTO:
871
872 if (ic && ic->ic_phytype == IEEE80211_T_FH) {
873 mask |= IFM_IEEE80211_FH;
874 break;
875 }
876
877
878 case IEEE80211_MODE_11G:
879 mask |= IFM_IEEE80211_11G;
880 break;
881 }
882 for (i = 0; i < N(rates); i++)
883 if (rates[i].m == mask)
884 return rates[i].r;
885 return IFM_AUTO;
886 #undef N
887 }
888
889 int
890 ieee80211_media2rate(int mword)
891 {
892 #define N(a) (sizeof(a) / sizeof(a[0]))
893 int i;
894 static const struct {
895 int subtype;
896 int rate;
897 } ieeerates[] = {
898 { IFM_AUTO, -1 },
899 { IFM_MANUAL, 0 },
900 { IFM_NONE, 0 },
901 { IFM_IEEE80211_FH1, 2 },
902 { IFM_IEEE80211_FH2, 4 },
903 { IFM_IEEE80211_DS1, 2 },
904 { IFM_IEEE80211_DS2, 4 },
905 { IFM_IEEE80211_DS5, 11 },
906 { IFM_IEEE80211_DS11, 22 },
907 { IFM_IEEE80211_DS22, 44 },
908 { IFM_IEEE80211_OFDM6, 12 },
909 { IFM_IEEE80211_OFDM9, 18 },
910 { IFM_IEEE80211_OFDM12, 24 },
911 { IFM_IEEE80211_OFDM18, 36 },
912 { IFM_IEEE80211_OFDM24, 48 },
913 { IFM_IEEE80211_OFDM36, 72 },
914 { IFM_IEEE80211_OFDM48, 96 },
915 { IFM_IEEE80211_OFDM54, 108 },
916 { IFM_IEEE80211_OFDM72, 144 },
917 };
918 for (i = 0; i < N(ieeerates); i++) {
919 if (ieeerates[i].subtype == IFM_SUBTYPE(mword))
920 return ieeerates[i].rate;
921 }
922 return 0;
923 #undef N
924 }