nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /*************************************************************************** |
2 | * * |
||
3 | * ########### ########### ########## ########## * |
||
4 | * ############ ############ ############ ############ * |
||
5 | * ## ## ## ## ## ## ## * |
||
6 | * ## ## ## ## ## ## ## * |
||
7 | * ########### #### ###### ## ## ## ## ###### * |
||
8 | * ########### #### # ## ## ## ## # # * |
||
9 | * ## ## ###### ## ## ## ## # # * |
||
10 | * ## ## # ## ## ## ## # # * |
||
11 | * ############ ##### ###### ## ## ## ##### ###### * |
||
12 | * ########### ########### ## ## ## ########## * |
||
13 | * * |
||
14 | * S E C U R E M O B I L E N E T W O R K I N G * |
||
15 | * * |
||
16 | * This file is part of NexMon. * |
||
17 | * * |
||
18 | * Copyright (c) 2016 NexMon Team * |
||
19 | * * |
||
20 | * NexMon is free software: you can redistribute it and/or modify * |
||
21 | * it under the terms of the GNU General Public License as published by * |
||
22 | * the Free Software Foundation, either version 3 of the License, or * |
||
23 | * (at your option) any later version. * |
||
24 | * * |
||
25 | * NexMon is distributed in the hope that it will be useful, * |
||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
||
28 | * GNU General Public License for more details. * |
||
29 | * * |
||
30 | * You should have received a copy of the GNU General Public License * |
||
31 | * along with NexMon. If not, see <http://www.gnu.org/licenses/>. * |
||
32 | * * |
||
33 | **************************************************************************/ |
||
34 | |||
35 | #pragma NEXMON targetregion "patch" |
||
36 | |||
37 | #include <firmware_version.h> // definition of firmware version macros |
||
38 | #include <debug.h> // contains macros to access the debug hardware |
||
39 | #include <wrapper.h> // wrapper definitions for functions that already exist in the firmware |
||
40 | #include <structs.h> // structures that are used by the code in the firmware |
||
41 | #include <helper.h> // useful helper functions |
||
42 | #include <patcher.h> // macros used to craete patches such as BLPatch, BPatch, ... |
||
43 | #include <rates.h> // rates used to build the ratespec for frame injection |
||
44 | #include <nexioctls.h> // ioctls added in the nexmon patch |
||
45 | #include <argprintf.h> |
||
46 | |||
47 | /** |
||
48 | * Setup a timer to schedule a function call |
||
49 | */ |
||
50 | struct hndrte_timer * |
||
51 | schedule_work(void *context, void *data, void *mainfn, int ms, int periodic) |
||
52 | { |
||
53 | struct hndrte_timer *task; |
||
54 | task = hndrte_init_timer(context, data, mainfn, 0); |
||
55 | if (task) { |
||
56 | if(!hndrte_add_timer(task, ms, periodic)) |
||
57 | hndrte_free_timer(task); |
||
58 | } |
||
59 | return task; |
||
60 | } |
||
61 | |||
62 | struct delayed_task { |
||
63 | void *context; |
||
64 | void *data; |
||
65 | void *mainfn; |
||
66 | int ms; |
||
67 | int periodic; |
||
68 | }; |
||
69 | |||
70 | static void |
||
71 | perform_delayed_task(struct hndrte_timer *t) |
||
72 | { |
||
73 | struct delayed_task *delayed_task = (struct delayed_task *) t->data; |
||
74 | |||
75 | schedule_work(delayed_task->context, delayed_task->data, delayed_task->mainfn, delayed_task->ms, delayed_task->periodic); |
||
76 | |||
77 | free(t->data); |
||
78 | } |
||
79 | |||
80 | struct hndrte_timer * |
||
81 | schedule_delayed_work(void *context, void *data, void *mainfn, int ms, int periodic, int delay_ms) |
||
82 | { |
||
83 | struct hndrte_timer *task; |
||
84 | struct delayed_task *delayed_task = malloc(sizeof(struct delayed_task), 0); |
||
85 | |||
86 | delayed_task->context = context; |
||
87 | delayed_task->data = data; |
||
88 | delayed_task->mainfn = mainfn; |
||
89 | delayed_task->ms = ms; |
||
90 | delayed_task->periodic = periodic; |
||
91 | |||
92 | task = hndrte_init_timer(context, delayed_task, perform_delayed_task, 0); |
||
93 | if (task) { |
||
94 | if(!hndrte_add_timer(task, delay_ms, 0)) |
||
95 | hndrte_free_timer(task); |
||
96 | } |
||
97 | return task; |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * add data to the start of a buffer |
||
102 | */ |
||
103 | void * |
||
104 | skb_push(sk_buff *p, unsigned int len) |
||
105 | { |
||
106 | p->data -= len; |
||
107 | p->len += len; |
||
108 | |||
109 | //if (p->data < p->head) |
||
110 | // printf("%s: failed", __FUNCTION__); |
||
111 | |||
112 | return p->data; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * remove data from the start of a buffer |
||
117 | */ |
||
118 | void * |
||
119 | skb_pull(sk_buff *p, unsigned int len) |
||
120 | { |
||
121 | p->data += len; |
||
122 | p->len -= len; |
||
123 | |||
124 | return p->data; |
||
125 | } |
||
126 | |||
127 | void |
||
128 | _hexdump(char *desc, void *addr, int len, int (*_printf)(const char *, ...)) |
||
129 | { |
||
130 | int i; |
||
131 | unsigned char buff[17]; |
||
132 | unsigned char *pc = (unsigned char*)addr; |
||
133 | |||
134 | // Output description if given. |
||
135 | if (desc != 0) |
||
136 | _printf("%s:\n", desc); |
||
137 | |||
138 | // Process every byte in the data. |
||
139 | for (i = 0; i < len; i++) { |
||
140 | // Multiple of 16 means new line (with line offset). |
||
141 | |||
142 | if ((i % 16) == 0) { |
||
143 | // Just don't print ASCII for the zeroth line. |
||
144 | if (i != 0) |
||
145 | _printf(" %s\n", buff); |
||
146 | |||
147 | // Output the offset. |
||
148 | _printf(" %04x ", i); |
||
149 | } |
||
150 | |||
151 | // Now the hex code for the specific character. |
||
152 | _printf(" %02x", pc[i]); |
||
153 | |||
154 | // And store a printable ASCII character for later. |
||
155 | if ((pc[i] < 0x20) || (pc[i] > 0x7e)) |
||
156 | buff[i % 16] = '.'; |
||
157 | else |
||
158 | buff[i % 16] = pc[i]; |
||
159 | buff[(i % 16) + 1] = '\0'; |
||
160 | } |
||
161 | |||
162 | // Pad out last line if not exactly 16 characters. |
||
163 | while ((i % 16) != 0) { |
||
164 | _printf(" "); |
||
165 | i++; |
||
166 | } |
||
167 | |||
168 | // And print the final ASCII bit. |
||
169 | _printf(" %s\n", buff); |
||
170 | } |
||
171 | |||
172 | void |
||
173 | hexdump(char *desc, void *addr, int len) |
||
174 | { |
||
175 | _hexdump(desc, addr, len, printf); |
||
176 | } |
||
177 | |||
178 | |||
179 | /* Quarter dBm units to mW |
||
180 | * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 |
||
181 | * Table is offset so the last entry is largest mW value that fits in |
||
182 | * a uint16. |
||
183 | */ |
||
184 | |||
185 | #define QDBM_OFFSET 153 /* Offset for first entry */ |
||
186 | #define QDBM_TABLE_LEN 40 /* Table size */ |
||
187 | |||
188 | /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. |
||
189 | * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 |
||
190 | */ |
||
191 | #define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ |
||
192 | |||
193 | /* Largest mW value that will round down to the last table entry, |
||
194 | * QDBM_OFFSET + QDBM_TABLE_LEN-1. |
||
195 | * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. |
||
196 | */ |
||
197 | #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ |
||
198 | |||
199 | static const unsigned short nqdBm_to_mW_map[QDBM_TABLE_LEN] = { |
||
200 | /* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ |
||
201 | /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, |
||
202 | /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, |
||
203 | /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, |
||
204 | /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, |
||
205 | /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 |
||
206 | }; |
||
207 | |||
208 | unsigned short |
||
209 | bcm_qdbm_to_mw(unsigned char qdbm) |
||
210 | { |
||
211 | unsigned int factor = 1; |
||
212 | int idx = qdbm - QDBM_OFFSET; |
||
213 | |||
214 | if (idx >= QDBM_TABLE_LEN) { |
||
215 | /* clamp to max uint16 mW value */ |
||
216 | return 0xFFFF; |
||
217 | } |
||
218 | |||
219 | /* scale the qdBm index up to the range of the table 0-40 |
||
220 | * where an offset of 40 qdBm equals a factor of 10 mW. |
||
221 | */ |
||
222 | while (idx < 0) { |
||
223 | idx += 40; |
||
224 | factor *= 10; |
||
225 | } |
||
226 | |||
227 | /* return the mW value scaled down to the correct factor of 10, |
||
228 | * adding in factor/2 to get proper rounding. |
||
229 | */ |
||
230 | return ((nqdBm_to_mW_map[idx] + factor/2) / factor); |
||
231 | } |
||
232 | |||
233 | unsigned char |
||
234 | bcm_mw_to_qdbm(unsigned short mw) |
||
235 | { |
||
236 | unsigned char qdbm; |
||
237 | int offset; |
||
238 | unsigned int mw_uint = mw; |
||
239 | unsigned int boundary; |
||
240 | |||
241 | /* handle boundary case */ |
||
242 | if (mw_uint <= 1) |
||
243 | return 0; |
||
244 | |||
245 | offset = QDBM_OFFSET; |
||
246 | |||
247 | /* move mw into the range of the table */ |
||
248 | while (mw_uint < QDBM_TABLE_LOW_BOUND) { |
||
249 | mw_uint *= 10; |
||
250 | offset -= 40; |
||
251 | } |
||
252 | |||
253 | for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { |
||
254 | boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - |
||
255 | nqdBm_to_mW_map[qdbm])/2; |
||
256 | if (mw_uint < boundary) break; |
||
257 | } |
||
258 | |||
259 | qdbm += (uint8)offset; |
||
260 | |||
261 | return (qdbm); |
||
262 | } |
||
263 | |||
264 | void |
||
265 | set_chanspec(struct wlc_info *wlc, unsigned short chanspec) |
||
266 | { |
||
267 | unsigned int local_chanspec = chanspec; |
||
268 | wlc_iovar_op(wlc, "chanspec", 0, 0, &local_chanspec, 4, 1, 0); |
||
269 | } |
||
270 | |||
271 | unsigned int |
||
272 | get_chanspec(struct wlc_info *wlc) |
||
273 | { |
||
274 | unsigned int chanspec = 0; |
||
275 | wlc_iovar_op(wlc, "chanspec", 0, 0, &chanspec, 4, 0, 0); |
||
276 | return chanspec; |
||
277 | } |
||
278 | |||
279 | void |
||
280 | set_mpc(struct wlc_info *wlc, uint32 mpc) |
||
281 | { |
||
282 | wlc_iovar_op(wlc, "mpc", 0, 0, &mpc, 4, 1, 0); |
||
283 | } |
||
284 | |||
285 | uint32 |
||
286 | get_mpc(struct wlc_info *wlc) |
||
287 | { |
||
288 | uint32 mpc = 0; |
||
289 | |||
290 | wlc_iovar_op(wlc, "mpc", 0, 0, &mpc, 4, 0, 0); |
||
291 | |||
292 | return mpc; |
||
293 | } |
||
294 | |||
295 | void |
||
296 | set_monitormode(struct wlc_info *wlc, uint32 monitor) |
||
297 | { |
||
298 | wlc_ioctl(wlc, WLC_SET_MONITOR, &monitor, 4, 0); |
||
299 | } |
||
300 | |||
301 | void |
||
302 | set_intioctl(struct wlc_info *wlc, uint32 cmd, uint32 arg) |
||
303 | { |
||
304 | wlc_ioctl(wlc, cmd, &arg, 4, 0); |
||
305 | } |
||
306 | |||
307 | uint32 |
||
308 | get_intioctl(struct wlc_info *wlc, uint32 cmd) |
||
309 | { |
||
310 | uint32 arg; |
||
311 | wlc_ioctl(wlc, cmd, &arg, 4, 0); |
||
312 | return arg; |
||
313 | } |
||
314 | |||
315 | #if (NEXMON_CHIP == CHIP_VER_BCM4339 || NEXMON_CHIP == CHIP_VER_BCM4358 || NEXMON_CHIP == CHIP_VER_BCM43455c0) |
||
316 | void |
||
317 | set_scansuppress(struct wlc_info *wlc, uint32 scansuppress) |
||
318 | { |
||
319 | wlc_scan_ioctl(wlc->scan, WLC_SET_SCANSUPPRESS, &scansuppress, 4, 0); |
||
320 | } |
||
321 | |||
322 | uint32 |
||
323 | get_scansuppress(struct wlc_info *wlc) |
||
324 | { |
||
325 | uint32 scansuppress = 0; |
||
326 | |||
327 | wlc_scan_ioctl(wlc->scan, WLC_GET_SCANSUPPRESS, &scansuppress, 4, 0); |
||
328 | |||
329 | return scansuppress; |
||
330 | } |
||
331 | #endif |