Original 20051017 tarball
[acx-mac80211.git] / setrate.c
blobe9fdbd626e3f99fdfdcfdc55ed61d61e0f06b2da
1 /* TODO: stop #including, move into wireless.c
2 * until then, keep in sync copies in prism54/ and acx/ dirs
3 * code+data size: less than 1k */
5 enum {
6 DOT11_RATE_1,
7 DOT11_RATE_2,
8 DOT11_RATE_5,
9 DOT11_RATE_11,
10 DOT11_RATE_22,
11 DOT11_RATE_33,
12 DOT11_RATE_6,
13 DOT11_RATE_9,
14 DOT11_RATE_12,
15 DOT11_RATE_18,
16 DOT11_RATE_24,
17 DOT11_RATE_36,
18 DOT11_RATE_48,
19 DOT11_RATE_54
21 enum {
22 DOT11_MOD_DBPSK,
23 DOT11_MOD_DQPSK,
24 DOT11_MOD_CCK,
25 DOT11_MOD_OFDM,
26 DOT11_MOD_CCKOFDM,
27 DOT11_MOD_PBCC
29 static const u8 ratelist[] = { 1,2,5,11,22,33,6,9,12,18,24,36,48,54 };
30 static const u8 dot11ratebyte[] = { 1*2,2*2,11,11*2,22*2,33*2,6*2,9*2,12*2,18*2,24*2,36*2,48*2,54*2 };
31 static const u8 default_modulation[] = {
32 DOT11_MOD_DBPSK,
33 DOT11_MOD_DQPSK,
34 DOT11_MOD_CCK,
35 DOT11_MOD_CCK,
36 DOT11_MOD_PBCC,
37 DOT11_MOD_PBCC,
38 DOT11_MOD_OFDM,
39 DOT11_MOD_OFDM,
40 DOT11_MOD_OFDM,
41 DOT11_MOD_OFDM,
42 DOT11_MOD_OFDM,
43 DOT11_MOD_OFDM,
44 DOT11_MOD_OFDM,
45 DOT11_MOD_OFDM
48 static /* TODO: remove 'static' when moved to wireless.c */
49 int
50 rate_mbit2enum(int n) {
51 int i=0;
52 while(i<sizeof(ratelist)) {
53 if(n==ratelist[i]) return i;
54 i++;
56 return -EINVAL;
59 static int
60 get_modulation(int r_enum, char suffix) {
61 if(suffix==',' || suffix==' ' || suffix=='\0') {
62 /* could shorten default_mod by 8 bytes:
63 if(r_enum>=DOT11_RATE_6) return DOT11_MOD_OFDM; */
64 return default_modulation[r_enum];
66 if(suffix=='c') {
67 if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_11) return -EINVAL;
68 return DOT11_MOD_CCK;
70 if(suffix=='p') {
71 if(r_enum<DOT11_RATE_5 || r_enum>DOT11_RATE_33) return -EINVAL;
72 return DOT11_MOD_PBCC;
74 if(suffix=='o') {
75 if(r_enum<DOT11_RATE_6) return -EINVAL;
76 return DOT11_MOD_OFDM;
78 if(suffix=='d') {
79 if(r_enum<DOT11_RATE_6) return -EINVAL;
80 return DOT11_MOD_CCKOFDM;
82 return -EINVAL;
85 #ifdef UNUSED
86 static int
87 fill_ratevector(const char **pstr, u8 *vector, int size,
88 int (*supported)(int mbit, int mod, void *opaque), void *opaque, int or_mask)
90 unsigned long rate_mbit;
91 int rate_enum,mod;
92 const char *str = *pstr;
93 char c;
95 do {
96 rate_mbit = simple_strtoul(str, (char**)&str, 10);
97 if(rate_mbit>INT_MAX) return -EINVAL;
99 rate_enum = rate_mbit2enum(rate_mbit);
100 if(rate_enum<0) return rate_enum;
102 c = *str;
103 mod = get_modulation(rate_enum, c);
104 if(mod<0) return mod;
106 if(c>='a' && c<='z') c = *++str;
107 if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
109 if(supported) {
110 int r = supported(rate_mbit, mod, opaque);
111 if(r) return r;
114 *vector++ = dot11ratebyte[rate_enum] | or_mask;
116 size--;
117 str++;
118 } while(size>0 && c==',');
120 if(size<1) return -E2BIG;
121 *vector=0; /* TODO: sort, remove dups? */
123 *pstr = str-1;
124 return 0;
127 static /* TODO: remove 'static' when moved to wireless.c */
129 fill_ratevectors(const char *str, u8 *brate, u8 *orate, int size,
130 int (*supported)(int mbit, int mod, void *opaque), void *opaque)
132 int r;
134 r = fill_ratevector(&str, brate, size, supported, opaque, 0x80);
135 if(r) return r;
137 orate[0] = 0;
138 if(*str==' ') {
139 str++;
140 r = fill_ratevector(&str, orate, size, supported, opaque, 0);
141 if(r) return r;
142 /* TODO: sanitize, e.g. remove/error on rates already in basic rate set? */
144 if(*str)
145 return -EINVAL;
147 return 0;
149 #endif
151 /* TODO: use u64 masks? */
153 static int
154 fill_ratemask(const char **pstr, u32* mask,
155 int (*supported)(int mbit, int mod,void *opaque),
156 u32 (*gen_mask)(int mbit, int mod,void *opaque),
157 void *opaque)
159 unsigned long rate_mbit;
160 int rate_enum,mod;
161 u32 m = 0;
162 const char *str = *pstr;
163 char c;
165 do {
166 rate_mbit = simple_strtoul(str, (char**)&str, 10);
167 if(rate_mbit>INT_MAX) return -EINVAL;
169 rate_enum = rate_mbit2enum(rate_mbit);
170 if(rate_enum<0) return rate_enum;
172 c = *str;
173 mod = get_modulation(rate_enum, c);
174 if(mod<0) return mod;
176 if(c>='a' && c<='z') c = *++str;
177 if(c!=',' && c!=' ' && c!='\0') return -EINVAL;
179 if(supported) {
180 int r = supported(rate_mbit, mod, opaque);
181 if(r) return r;
184 m |= gen_mask(rate_mbit, mod, opaque);
185 str++;
186 } while(c==',');
188 *pstr = str-1;
189 *mask |= m;
190 return 0;
193 static /* TODO: remove 'static' when moved to wireless.c */
195 fill_ratemasks(const char *str, u32 *bmask, u32 *omask,
196 int (*supported)(int mbit, int mod,void *opaque),
197 u32 (*gen_mask)(int mbit, int mod,void *opaque),
198 void *opaque)
200 int r;
202 r = fill_ratemask(&str, bmask, supported, gen_mask, opaque);
203 if(r) return r;
205 if(*str==' ') {
206 str++;
207 r = fill_ratemask(&str, omask, supported, gen_mask, opaque);
208 if(r) return r;
210 if(*str)
211 return -EINVAL;
212 return 0;