IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Commit Details
Date: | 2011-01-19 07:22:24 (9 years 11 months ago) |
---|---|
Author: | Werner Almesberger |
Commit: | f9aee543234110dba3d0a2104024a668a1bc32ae |
Message: | atrf-txrx: added ability to record received frames in pcap format - pcap.h: basic pcap file structure definitions - atrf-txrx.c (usage, main): added option "-o file" to write received frames to a pcap file instead of displaying them - atrf-txrx.c (receive): moved code to receive and display a single message into new function receive_message - atrf-txrx.c (write_pcap_hdr, write_pcap_rec, receive_pcap): receive messages into a pcap file |
Files: |
tools/atrf-txrx/atrf-txrx.c (7 diffs) tools/atrf-txrx/pcap.h (1 diff) |
Change Details
tools/atrf-txrx/atrf-txrx.c | ||
---|---|---|
19 | 19 | #include <math.h> |
20 | 20 | #include <signal.h> |
21 | 21 | #include <sys/wait.h> |
22 | #include <sys/time.h> | |
22 | 23 | |
23 | 24 | #include "at86rf230.h" |
24 | 25 | #include "atrf.h" |
25 | 26 | #include "misctxrx.h" |
26 | 27 | |
28 | #include "pcap.h" | |
29 | ||
27 | 30 | |
28 | 31 | /* |
29 | 32 | * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only |
... | ... | |
148 | 151 | } |
149 | 152 | |
150 | 153 | |
151 | static void receive(struct atrf_dsc *dsc) | |
154 | static void receive_message(struct atrf_dsc *dsc) | |
152 | 155 | { |
153 | 156 | uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */ |
154 | 157 | int n, ok, i; |
155 | 158 | uint8_t ed, lqi; |
156 | 159 | |
157 | atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); | |
158 | /* | |
159 | * 180 us, according to AVR2001 section 4.2. We time out after | |
160 | * nominally 200 us. | |
161 | */ | |
162 | wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20); | |
163 | ||
164 | 160 | fprintf(stderr, "Ready.\n"); |
165 | 161 | wait_for_interrupt(dsc, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START, |
166 | 162 | 10, 0); |
... | ... | |
185 | 181 | } |
186 | 182 | |
187 | 183 | |
184 | static void write_pcap_hdr(FILE *file) | |
185 | { | |
186 | struct pcap_file_header hdr = { | |
187 | .magic = 0xa1b2c3d4, | |
188 | .version_major = 2, | |
189 | .version_minor = 4, | |
190 | .thiszone = 0, | |
191 | .sigfigs = 0, | |
192 | .snaplen = MAX_PSDU, | |
193 | .linktype = DLT_IEEE802_15_4 | |
194 | }; | |
195 | ||
196 | if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) { | |
197 | perror("fwrite"); | |
198 | exit(1); | |
199 | } | |
200 | } | |
201 | ||
202 | ||
203 | static void write_pcap_rec(FILE *file, const struct timeval *tv, | |
204 | const void *buf, int n) | |
205 | { | |
206 | struct pcap_pkthdr hdr = { | |
207 | .ts_sec = tv->tv_sec, | |
208 | .ts_usec = tv->tv_usec, | |
209 | .caplen = n, | |
210 | .len = n | |
211 | }; | |
212 | ||
213 | if (fwrite(&hdr, sizeof(hdr), 1, file) != 1) { | |
214 | perror("fwrite"); | |
215 | exit(1); | |
216 | } | |
217 | if (fwrite(buf, n, 1, file) != 1) { | |
218 | perror("fwrite"); | |
219 | exit(1); | |
220 | } | |
221 | } | |
222 | ||
223 | ||
224 | static void receive_pcap(struct atrf_dsc *dsc, const char *name) | |
225 | { | |
226 | FILE *file; | |
227 | uint8_t buf[MAX_PSDU+1]; /* PSDU+LQI */ | |
228 | struct timeval now; | |
229 | int n; | |
230 | int count = 0; | |
231 | ||
232 | file = fopen(name, "w"); | |
233 | if (!file) { | |
234 | perror(name); | |
235 | exit(1); | |
236 | } | |
237 | write_pcap_hdr(file); | |
238 | while (run) { | |
239 | wait_for_interrupt(dsc, | |
240 | IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START, | |
241 | 10, 0); | |
242 | if (!run) | |
243 | break; | |
244 | gettimeofday(&now, NULL); | |
245 | n = atrf_buf_read(dsc, buf, sizeof(buf)); | |
246 | if (n < 0) | |
247 | exit(1); | |
248 | if (n < 2) { | |
249 | fprintf(stderr, "%d bytes received\n", n); | |
250 | continue; | |
251 | } | |
252 | write_pcap_rec(file, &now, buf, n-1); | |
253 | (void) write(2, ".", 1); | |
254 | count++; | |
255 | } | |
256 | if (fclose(file) == EOF) { | |
257 | perror(name); | |
258 | exit(1); | |
259 | } | |
260 | fprintf(stderr, "%sreceived %d message%s\n", count ? "\n" : "", | |
261 | count, count == 1 ? "" : "s"); | |
262 | } | |
263 | ||
264 | ||
265 | static void receive(struct atrf_dsc *dsc, const char *name) | |
266 | { | |
267 | atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); | |
268 | /* | |
269 | * 180 us, according to AVR2001 section 4.2. We time out after | |
270 | * nominally 200 us. | |
271 | */ | |
272 | wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20); | |
273 | ||
274 | if (name) | |
275 | receive_pcap(dsc, name); | |
276 | else | |
277 | receive_message(dsc); | |
278 | } | |
279 | ||
280 | ||
188 | 281 | static void transmit(struct atrf_dsc *dsc, const char *msg, int times) |
189 | 282 | { |
190 | 283 | uint8_t buf[MAX_PSDU]; |
... | ... | |
332 | 425 | " wave in MHz: -2, -0.5, or +0.5\n" |
333 | 426 | " command shell command to run while transmitting (default: wait for\n" |
334 | 427 | " SIGINT instead)\n\n" |
335 | " common options: [-c channel|-f freq] [-C mhz] [-p power] [-t trim]\n" | |
428 | " common options: [-c channel|-f freq] [-C mhz] [-o file] [-p power] " | |
429 | "[-t trim]\n" | |
336 | 430 | " -c channel channel number, 11 to 26 (default %d)\n" |
337 | 431 | " -C mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\n" |
338 | 432 | " -f freq frequency in MHz, 2405 to 2480 (default %d)\n" |
433 | " -o file write received data to a file in pcap format\n" | |
339 | 434 | " -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n" |
340 | 435 | " -t trim trim capacitor, 0 to 15 (default 0)\n" |
341 | 436 | , name, name, DEFAULT_CHANNEL, 2405+5*(DEFAULT_CHANNEL-11), |
... | ... | |
354 | 449 | int c, freq; |
355 | 450 | unsigned tmp, clkm = 0; |
356 | 451 | int status = 0; |
452 | const char *pcap_file = NULL; | |
357 | 453 | struct atrf_dsc *dsc; |
358 | 454 | |
359 | while ((c = getopt(argc, argv, "c:C:f:p:t:T:")) != EOF) | |
455 | while ((c = getopt(argc, argv, "c:C:f:o:p:t:T:")) != EOF) | |
360 | 456 | switch (c) { |
361 | 457 | case 'c': |
362 | 458 | channel = strtoul(optarg, &end, 0); |
... | ... | |
375 | 471 | if (channel < 11 || channel > 26) |
376 | 472 | usage(*argv); |
377 | 473 | break; |
474 | case 'o': | |
475 | pcap_file = optarg; | |
476 | break; | |
378 | 477 | case 'p': |
379 | 478 | power = strtod(optarg, &end); |
380 | 479 | if (*end) |
... | ... | |
419 | 518 | dsc = init_txrx(trim, clkm); |
420 | 519 | set_channel(dsc, channel); |
421 | 520 | if (!cont_tx) |
422 | receive(dsc); | |
521 | receive(dsc, pcap_file); | |
423 | 522 | else { |
424 | 523 | set_power(dsc, power, 0); |
425 | 524 | status = test_mode(dsc, cont_tx, NULL); |
tools/atrf-txrx/pcap.h | ||
---|---|---|
1 | /* | |
2 | * pcap.h - Minimum pcap file definitions | |
3 | * | |
4 | * Written 2011 by Werner Almesberger | |
5 | * Copyright 2011 Werner Almesberger | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | */ | |
12 | ||
13 | /* | |
14 | * This header defines the few things we need to write files in the pcap | |
15 | * format. The identifiers are the same as in the system's pcap/pcap.h, but | |
16 | * the types have been standardized. Note that the timestamp parts have to be | |
17 | * put separately, since "struct timeval" may be padded. | |
18 | * | |
19 | * The reason for having our own header instead of just using pcap/pcap.h is | |
20 | * to avoid a build-dependency on libpcap. | |
21 | */ | |
22 | ||
23 | #ifndef PCAP_H | |
24 | #define PCAP_H | |
25 | ||
26 | #include <stdint.h> | |
27 | #include <sys/time.h> | |
28 | ||
29 | ||
30 | #define DLT_IEEE802_15_4 195 | |
31 | ||
32 | struct pcap_file_header { | |
33 | uint32_t magic; | |
34 | uint16_t version_major; | |
35 | uint16_t version_minor; | |
36 | int32_t thiszone; | |
37 | uint32_t sigfigs; | |
38 | uint32_t snaplen; | |
39 | uint32_t linktype; | |
40 | }; | |
41 | ||
42 | struct pcap_pkthdr { | |
43 | uint32_t ts_sec; | |
44 | uint32_t ts_usec; | |
45 | uint32_t caplen; | |
46 | uint32_t len; | |
47 | }; | |
48 | ||
49 | #endif /* !PCAP_H */ |