nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
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