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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
|
<pre>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ RTLSDR usage +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ INDEX +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1. Setup rtlsdr
1.1. Get sources
1.2. Drivers
1.3. Check if works
2. Collection of tools
2.1. FM
2.2. Spectrum diagram
2.3. ADSB
2.4. AFSK1200
3. Projects where rtlsdr used
3.1. WebSDR
4. Problems
4.1. Sync errors
5. Links
6. Changelog
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1.Setup rtlsdr +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
By rtlsdr usually call RTL2832U chip based tv-tunners which
can be used for not just recievin DVB-T frequencies but much more
and yes price is ~$10 it mean that anyone can just buy and try
without "loosing" money.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1.1.Get sources
Main development repository is on http://sdr.osmocom.org/trac/wiki/rtl-sdr
on github you can find more repos with experminental
features (https://github.com/keenerd/rtl-sdr).
Getting sources from git:
git clone git://git.osmocom.org/rtl-sdr.git
I prefer using plain binaries without any kind of installation. Just
compile and use binary without any troubles.
Build:
cmake .
make
All binaries is in src dir
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1.2.Drivers
Linux kernel have some drivers for rtlsdr stick and DVB-T. When you will plug
rtlsdr then kernel probably will load DVB-T drivers and you will not able
to use you rtlsdr for sdr. Way yo fix is it add some drivers to black list and
next time when you will plug rtlsdr this drivers will not be loaded.
Check if rtlsdr related drivers is loaded:
lsmod | grep rtl28
If there is some drivers then balcklist driver by creating file
in /etc/modprobe.d/ with content:
blacklist dvb_usb_rtl28xxu
Next thing that could appear is permissions on rtlsdr usage when its pluged in.
To allow everyone to use create file in /etc/udev/rules.d/ with content:
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", \
GROUP="adm", MODE="0666", SYMLINK+="rtl_sdr"
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1.3.Check if works
How to test if rtlsdr works? Run one of commands:
rtl_test
I like to run rtl_adsb as you can see there that something is recieved and
you see that everything "works":
rtl_adsb
There should be line by line showing up some "hex" lines. If some data is showen
then adsb data from plains is recieved.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2.Collection of tools +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.1.FM
Get some sound trancmited from FM radio stations.
rtl_fm -f 96.3e6 -M wbfm -s 200000 -r 48000 - | aplay -r 48k -f S16_LE
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.2.Spectrum diagram
Scan spectrum to find some activities on different frequencies.
Good link with all description is http://kmkeen.com/rtl-power/ .
Main usage of rtl_power is :
rtl_power -f 76M:108M:125k -i 1 fm_stations.csv
and then draw image :
heatmap.py fm_stations.csv fm_stations.png
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.3.ADSB
ADS-B ( Automatic dependent surveillance broadcast ) in simple words airplain
geoposition, speed, height and flight number broadcasting. You can recieve
this data and see how many plains is around and sometimes flight number.
rtlsdr have default one rtl_adsb programm but it shows only recieved data,
without any decoding. Here is dump1090 specifically for rtlsdr and nothing
more:
https://github.com/antirez/dump1090
description howto install could be found also here
http://www.satsignal.eu/raspberry-pi/dump1090.html
Using in interactive mode with height in metrs:
dump1090 --interactive --metric
Output:
Hex Flight Altitude Speed Lat Lon Track Messages Seen .
------------------------------------------------------------------------------
71be01 10052 1009 36.434 33.544 45 9 1 sec
424913 SDM6329 10966 711 36.440 33.405 221 65 0 sec
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2.4.AFSK1200
Gqrx is graphical SDR software where you can travel across frequencies
and in real time search for some transmission.
http://gqrx.dk/
It have builtin AFSK1200 demodulator or in simple words ham radio packets.
And you could try to see what people sending in tex around the world.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3.Projects where rtlsdr used +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3.1.WebSDR
WebSDR probably best site where you can go and click on some radio reciever
and liste what happends in some particular country. WebSDR site contains
about 80 radio recievers around the world that can be accessed trought web
interface.
http://websdr.org/
If you whant setup your own radio reciever read FAQ, prepare mail and send mail
after that you could recieve precompiled websdr software with is easy
to setup with rtlsdr stick.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4.Problems +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4.1.Sync errors
Once there was sync error when was trying to use rtl_test or rtl_adsb.
To fix that changes for better quality usb cable.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 5.Links +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[1] http://kmkeen.com/rtl-demod-guide/
[2] http://kmkeen.com/rtl-power/
[3] http://sdr.osmocom.org/trac/wiki/rtl-sdr
[4] http://www.rtl-sdr.com/
[5] https://github.com/antirez/dump1090
[6] http://gqrx.dk
</pre>
```c
#include <stdint.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <getopt.h>
struct ihex_binrec {
struct ihex_binrec *next; /* not part of the real data structure */
uint32_t addr;
uint16_t len;
uint8_t data[];
};
/**
* nybble/hex are little helpers to parse hexadecimal numbers to a byte value
**/
static uint8_t nybble(const uint8_t n)
{
if (n >= '0' && n <= '9') return n - '0';
else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
return 0;
}
static uint8_t hex(const uint8_t *data, uint8_t *crc)
{
uint8_t val = (nybble(data[0]) << 4) | nybble(data[1]);
*crc += val;
return val;
}
static int process_ihex(uint8_t *data, ssize_t size);
static void file_record(struct ihex_binrec *record);
static int output_records(int outfd);
static int sort_records = 0;
static int wide_records = 0;
static int include_jump = 0;
static int usage(void)
{
fprintf(stderr, "ihex2fw: Convert ihex files into binary "
"representation for use by Linux kernel\n");
fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n");
fprintf(stderr, " -w: wide records (16-bit length)\n");
fprintf(stderr, " -s: sort records by address\n");
fprintf(stderr, " -j: include records for CS:IP/EIP address\n");
return 1;
}
int main(int argc, char **argv)
{
int infd, outfd;
struct stat st;
uint8_t *data;
int opt;
while ((opt = getopt(argc, argv, "wsj")) != -1) {
switch (opt) {
case 'w':
wide_records = 1;
break;
case 's':
sort_records = 1;
break;
case 'j':
include_jump = 1;
break;
default:
return usage();
}
}
if (optind + 2 != argc)
return usage();
if (!strcmp(argv[optind], "-"))
infd = 0;
else
infd = open(argv[optind], O_RDONLY);
if (infd == -1) {
fprintf(stderr, "Failed to open source file: %s",
strerror(errno));
return usage();
}
if (fstat(infd, &st)) {
perror("stat");
return 1;
}
data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, infd, 0);
if (data == MAP_FAILED) {
perror("mmap");
return 1;
}
if (!strcmp(argv[optind+1], "-"))
outfd = 1;
else
outfd = open(argv[optind+1], O_TRUNC|O_CREAT|O_WRONLY, 0644);
if (outfd == -1) {
fprintf(stderr, "Failed to open destination file: %s",
strerror(errno));
return usage();
}
if (process_ihex(data, st.st_size))
return 1;
return output_records(outfd);
}
static int process_ihex(uint8_t *data, ssize_t size)
{
struct ihex_binrec *record;
uint32_t offset = 0;
uint32_t data32;
uint8_t type, crc = 0, crcbyte = 0;
int i, j;
int line = 1;
int len;
i = 0;
next_record:
/* search for the start of record character */
while (i < size) {
if (data[i] == '\n') line++;
if (data[i++] == ':') break;
}
/* Minimum record length would be about 10 characters */
if (i + 10 > size) {
fprintf(stderr, "Can't find valid record at line %d\n", line);
return -EINVAL;
}
len = hex(data + i, &crc); i += 2;
if (wide_records) {
len <<= 8;
len += hex(data + i, &crc); i += 2;
}
record = malloc((sizeof (*record) + len + 3) & ~3);
if (!record) {
fprintf(stderr, "out of memory for records\n");
return -ENOMEM;
}
memset(record, 0, (sizeof(*record) + len + 3) & ~3);
record->len = len;
/* now check if we have enough data to read everything */
if (i + 8 + (record->len * 2) > size) {
fprintf(stderr, "Not enough data to read complete record at line %d\n",
line);
return -EINVAL;
}
record->addr = hex(data + i, &crc) << 8; i += 2;
record->addr |= hex(data + i, &crc); i += 2;
type = hex(data + i, &crc); i += 2;
for (j = 0; j < record->len; j++, i += 2)
record->data[j] = hex(data + i, &crc);
/* check CRC */
crcbyte = hex(data + i, &crc); i += 2;
if (crc != 0) {
fprintf(stderr, "CRC failure at line %d: got 0x%X, expected 0x%X\n",
line, crcbyte, (unsigned char)(crcbyte-crc));
return -EINVAL;
}
/* Done reading the record */
switch (type) {
case 0:
/* old style EOF record? */
if (!record->len)
break;
record->addr += offset;
file_record(record);
goto next_record;
case 1: /* End-Of-File Record */
if (record->addr || record->len) {
fprintf(stderr, "Bad EOF record (type 01) format at line %d",
line);
return -EINVAL;
}
break;
case 2: /* Extended Segment Address Record (HEX86) */
case 4: /* Extended Linear Address Record (HEX386) */
if (record->addr || record->len != 2) {
fprintf(stderr, "Bad HEX86/HEX386 record (type %02X) at line %d\n",
type, line);
return -EINVAL;
}
/* We shouldn't really be using the offset for HEX86 because
* the wraparound case is specified quite differently. */
offset = record->data[0] << 8 | record->data[1];
offset <<= (type == 2 ? 4 : 16);
goto next_record;
case 3: /* Start Segment Address Record */
case 5: /* Start Linear Address Record */
if (record->addr || record->len != 4) {
fprintf(stderr, "Bad Start Address record (type %02X) at line %d\n",
type, line);
return -EINVAL;
}
memcpy(&data32, &record->data[0], sizeof(data32));
data32 = htonl(data32);
memcpy(&record->data[0], &data32, sizeof(data32));
/* These records contain the CS/IP or EIP where execution
* starts. If requested output this as a record. */
if (include_jump)
file_record(record);
goto next_record;
default:
fprintf(stderr, "Unknown record (type %02X)\n", type);
return -EINVAL;
}
return 0;
}
static struct ihex_binrec *records;
static void file_record(struct ihex_binrec *record)
{
struct ihex_binrec **p = &records;
while ((*p) && (!sort_records || (*p)->addr < record->addr))
p = &((*p)->next);
record->next = *p;
*p = record;
}
static int output_records(int outfd)
{
unsigned char zeroes[6] = {0, 0, 0, 0, 0, 0};
struct ihex_binrec *p = records;
while (p) {
uint16_t writelen = (p->len + 9) & ~3;
p->addr = htonl(p->addr);
p->len = htons(p->len);
if (write(outfd, &p->addr, writelen) != writelen)
return 1;
p = p->next;
}
/* EOF record is zero length, since we don't bother to represent
the type field in the binary version */
if (write(outfd, zeroes, 6) != 6)
return 1;
return 0;
}
```
|