Compare commits

...

1443 Commits

Author SHA1 Message Date
eric1tran 849a3b7329 Release 7.2 2022-03-10 02:53:19 +00:00
eric1tran b842f4a8ed skyaware lighttpd module replaced dump1090-fa. We can disable dump1090-fa module now 2022-03-07 21:09:42 +00:00
eric1tran 6fc48a8cef Bump version to 7.2 2022-03-02 18:10:43 +00:00
eric1tran 2e83305229 Version bump back to 7.2 2022-02-25 15:39:07 +00:00
eric1tran d0e87cc219 Remove OSM Black & White layer which is no longer in service 2022-02-16 19:56:02 +00:00
Eric Tran ac7b5759f7
SkyAware HTML/CSS cleanup (#171)
* Remove deprecated dump1090-fa/ html files and update dump1090-fa.install accordingly

* Remove deprecated lighttpd files and update paths/readmes

* SkyAware readme update

* More SkyAware readme updates

* Bump html/css script cache bust versions
2022-02-15 08:58:22 -06:00
Oliver Jowett 350664a13a
Merge pull request #169 from ffontaine/master
Makefile: set _POSIX_C_SOURCE
2022-01-15 20:44:22 +08:00
Fabrice Fontaine f24c932cf8 Makefile: set _POSIX_C_SOURCE
Set -D_POSIX_C_SOURCE=200112L to avoid the following build failure with
uclibc-ng:

anet.c: In function ‘anetTcpGenericConnect’:
anet.c:153:21: error: storage size of ‘gai_hints’ isn’t known
  153 |     struct addrinfo gai_hints;
      |                     ^~~~~~~~~

In file included from dump1090.h:83,
                 from dump1090.c:50:
compat/compat.h:46:3: error: conflicting types for ‘clockid_t’
   46 | } clockid_t;
      |   ^~~~~~~~~
In file included from /home/fabrice/buildroot/output/host/or1k-buildroot-linux-uclibc/sysroot/usr/include/sys/types.h:132,
                 from /home/fabrice/buildroot/output/host/or1k-buildroot-linux-uclibc/sysroot/usr/include/stdlib.h:198,
                 from dump1090.h:66,
                 from dump1090.c:50:
/home/fabrice/buildroot/output/host/or1k-buildroot-linux-uclibc/sysroot/usr/include/time.h:91:21: note: previous declaration of ‘clockid_t’ was here
   91 | typedef __clockid_t clockid_t;
      |                     ^~~~~~~~~

net_io.c: In function ‘writeJsonToFile’:
net_io.c:2122:18: error: ‘PATH_MAX’ undeclared (first use in this function)
 2122 |     char pathbuf[PATH_MAX];
      |                  ^~~~~~~~

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2022-01-15 10:54:32 +01:00
Oliver Jowett c35135cabf
Merge pull request #170 from CodyCodeman/fix-make-syntax-error-darwin
Darwin: Fix Makefile syntax error
2022-01-15 12:58:44 +08:00
Oliver Jowett 86885c2480 Version bump to 8.0~dev 2022-01-15 11:26:16 +08:00
Cody 3be128877d
Fix syntax error 2022-01-14 12:23:30 -06:00
eric1tran a13356d801 Release 7.1 2022-01-12 17:10:52 +00:00
eric1tran 855f71918e Revert "Revert the debian/rules changes"
This reverts commit f5185cbebe.
2022-01-12 15:00:08 +00:00
eric1tran f5185cbebe Revert the debian/rules changes 2022-01-12 13:37:55 +00:00
eric1tran 765b295479 Don't forget Stretch 2022-01-11 19:42:36 +00:00
eric1tran 778d85e75f Start dump1090-fa after installing due to behavioral change in compat 10 2022-01-11 19:19:33 +00:00
eric1tran fb959f0fc7 No change 7.1 release for PiAware 7.1 2022-01-11 13:40:48 +00:00
eric1tran fec0da4f0b Version bump to 7.1~dev 2022-01-11 13:37:42 +00:00
eric1tran 52cdd32d0f Mark as stable in changelog 2021-12-21 14:55:38 +00:00
eric1tran 4601566886 Update changelogs 2021-12-20 17:06:29 +00:00
eric1tran 23f5dfef2c Merge branch 'dev' into staging 2021-12-13 17:49:25 +00:00
eric1tran 42a5c2a978 Update aircraft db to 20211210 2021-12-10 12:57:59 +00:00
Oliver Jowett 65cd5fe441 Clean up AVR parsing a bit. Add length checks. Decode timestamps. 2021-12-09 18:37:50 +08:00
Oliver Jowett f932baa5fa Adaptive gain: more aggressively re-probe for a higher gain
following a decrease in gain due to an increased noise floor.

This is controlled by --adaptive-range-scan-delay and defaults
to 5 minutes (vs. the default rescan delay of 1 hour)
2021-12-07 17:29:50 +08:00
Oliver Jowett fa8a066b4c Disable cpufeatures on darwin/arm64 2021-12-07 15:18:58 +08:00
Oliver Jowett b645f7d4f2 Try to respect CFLAGS/CPPFLAGS as far as possible; move required extra flags into a separate var.
This means you can, in theory, completely override CFLAGS/CPPFLAGS without also having to
provide all the internal flags that the Makefile usually detects.

$ make CFLAGS=-qwerty
[...]
cc  -I. -DMODES_DUMP1090_VERSION=\"unknown\" -DMODES_DUMP1090_VARIANT=\"dump1090-fa\" -D_DEFAULT_SOURCE -DENABLE_CPUFEATURES -Icpu_features/include -DENABLE_RTLSDR -DENABLE_BLADERF -DENABLE_HACKRF -DENABLE_LIMESDR -DSTARCH_MIX_X86 -qwerty -std=c11 -fno-common -Wall -Wmissing-declarations -Werror -W -I/usr/include/ -I/usr/include/libusb-1.0 -I/usr/include/ -I/usr/include/ -I/usr/include/libusb-1.0  -c dump1090.c -o dump1090.o

Should fix #161
2021-12-07 15:12:49 +08:00
Oliver Jowett bc72177c8b Treat ARCH=arm64 like ARCH=aarch64 2021-12-07 13:17:02 +08:00
eric1tran 24c0248fc0 Openlayers cleanup. Remove v4.4.2 js/css files and remove source map files as minified files are not being used to begin with 2021-11-22 18:27:12 +00:00
Oliver Jowett cdbd6c77a9 Updates for bullseye, drop jessie support.
* dh-compat 10
 * no dh-systemd dependency
 * backport version for buster
 * teach prepare-build about bullseye
 * update stretch maintainer address
 * update Jenkinsfile (this will be broken until the builder machine is upgraded)
2021-11-22 19:29:30 +08:00
eric1tran 9b2cd0a5ba 7.0 Version bump 2021-11-01 19:29:34 +00:00
Oliver Jowett 059e48b82b Allow env vars (not only command line overrides) to set CPUFEATURES_{ARCH,UNAME}.
Change CPUFEATURES_{ARCH,UNAME} defaults to use {ARCH,UNAME} values.

Fixes #158
2021-09-23 13:24:59 +08:00
Oliver Jowett 5f7e7cf8e0 Version bump to 7.0~dev 2021-09-23 13:14:03 +08:00
Oliver Jowett 752a7aeac0 No-change 6.1 release for PiAware 6.1
Fix 6.0 changelog date format
2021-09-06 16:07:03 +08:00
Oliver Jowett 08c7ccbc8e Adaptive gain docs.
(These are not included in the build so don't need to re-tag 6.0)
2021-09-01 19:45:01 +08:00
eric1tran 9788588aba Release 6.0 & changelog 2021-08-31 21:26:24 +00:00
eric1tran 8b9dd42676 Merge branch 'dev' into staging 2021-08-24 16:52:07 +00:00
Oliver Jowett 14e6d5c3fa Rearrange config upgrade so upgrading a v6 config file
disables adaptive gain.

This is needed for the case where a v5 package with an unmodified
config file is upgraded. dpkg will install the v6 default config
file automatically so it will already be a v6 config by the time
that upgrade-config runs, but we do still need to go in and
disable adaptive gain.
2021-08-23 13:07:05 +08:00
eric1tran e8eeac4654 Merge branch 'dev' into staging 2021-08-18 18:40:20 +00:00
Eric Tran abf8fa2b00
Revert "CSS updates (including dark mode)" (#149) 2021-08-18 13:37:50 -05:00
eric1tran 06bc3c34cf Version bump to 6.0 2021-08-17 20:41:14 +00:00
Oliver Jowett 88fec00f17 Add VH- registration rule to public_html_merged, too 2021-08-17 21:12:23 +08:00
Oliver Jowett ae042eeb27 Update aircraft db to 20210817 (Australian registrations & types)
Update public_html db so it's in sync with public_html_merged
2021-08-17 15:03:34 +08:00
Oliver Jowett f45b2c6475 Add a deterministic registration rule for VH- registrations 2021-08-17 14:34:10 +08:00
eric1tran 2ba2f4da71 Update aircraft db to 20210816 2021-08-16 17:32:24 +00:00
eric1tran 29a6ae5102 Merge branch 'dev' of github.com:flightaware/dump1090 into dev 2021-08-16 17:16:37 +00:00
Oliver Jowett 0aac23e049 Enable rtlsdr bounce buffers on aarch64, too (thanks to @wiedehopf for the suggestion) 2021-08-11 17:28:47 +08:00
Oliver Jowett ef70374126 Report json write errors, with some rate limiting.
Fixes #129
2021-08-04 17:33:28 +08:00
Oliver Jowett 7d552a2ede Remove old testfile (no longer useful due to sampling rate changes)
fixes #135 (well, wallpapers over the cracks at least)
2021-08-04 17:22:10 +08:00
Oliver Jowett 8b0e8ce6e3 Merge just one commit (21d1fe0f11) from PR #143 2021-08-04 17:11:44 +08:00
Oliver Jowett e02d0d5ffa Regenerate starch-generated files 2021-08-04 17:08:00 +08:00
Oliver Jowett 871a7e685f Update starch to upstream commit 0c8249fa4bc523345c156885542e9192e8bf9420 2021-08-04 17:07:08 +08:00
Oliver Jowett dd53b36bdf
Merge pull request #142 from flightaware/mrar
MRAR Comm-B support
2021-08-03 21:28:58 +08:00
Oliver Jowett 26924e4efe
Merge pull request #144 from b3nn0/stratux-gain
Stratux output: include current receiver gain
2021-08-03 17:22:54 +08:00
Adrian Batzill 6785c56348 Stratux output: include current receiver gain 2021-07-30 12:32:45 +01:00
VirusPilot 21d1fe0f11
Update dump1090.c
corrected an obvious typo
2021-07-30 08:36:45 +02:00
Oliver Jowett 3367cc5a82 faup1090: bump TSV_VERSION to 9E for MRAR, Comm-B changes 2021-07-29 19:04:54 +08:00
Oliver Jowett fe36349083 faup1090: upload MRAR data 2021-07-29 19:04:54 +08:00
Oliver Jowett e0f794b1a5 Track MRAR data per-aircraft and emit in aircraft.json 2021-07-29 19:04:54 +08:00
Oliver Jowett 95ab1c0faa faup1090: upload unknown-format Comm-B messages on demand 2021-07-29 19:04:53 +08:00
Oliver Jowett fab8081322 Upload Comm-B GICB messages 2021-07-29 19:04:53 +08:00
Oliver Jowett 9d4e2230d2 Add a few more Comm-B EMPTY_RESPONSE cases 2021-07-29 19:04:52 +08:00
Oliver Jowett 825f959e4d Add skeletal BDS0,5 decoding.
These messages duplicate ADS-B messages so it's not clear why
they are being interrogated for, and we don't really trust them
enough to do anything with the position information. But
recognizing/decoding them where possible does let us exclude other
Comm-B message types, avoiding some false positives.
2021-07-29 19:04:52 +08:00
Oliver Jowett c148fdca84 Distinguish "unknown format" from "didn't even try to decode"
when decoding Comm-B messages
2021-07-29 19:04:51 +08:00
Oliver Jowett 9f146fcb71 Set mrar_source_valid correctly 2021-07-29 19:04:51 +08:00
Oliver Jowett cdc818a9f3 MRAR source=5 is bogus, don't decode that. 2021-07-29 19:04:50 +08:00
Oliver Jowett e3a8e00412 WIP on MRAR decoding 2021-07-29 19:04:49 +08:00
Oliver Jowett 6b8cac3922 Increase default adaptive gain rescan interval to 1 hour 2021-07-26 22:08:57 +08:00
Oliver Jowett 899ee2530c Add CONFIG_STYLE to default config for unambiguous detection of
new-style config. Try to handle un-upgraded config files in
start-dump1090-fa. Always pass --quiet to dump1090-fa.
2021-07-26 20:26:17 +08:00
Oliver Jowett d6405ddefd Ignore bogus -I/ from librtlsdr pkgconfig 2021-07-26 20:25:35 +08:00
Oliver Jowett e058929977 stretch compile fixes? round two 2021-07-21 20:51:57 +08:00
Oliver Jowett 7b1771cdad Fix limesdr build 2021-07-21 20:03:06 +08:00
Oliver Jowett 017e5d391b Add ADAPTIVE_DYNAMIC_RANGE_TARGET config var 2021-07-21 19:42:09 +08:00
Oliver Jowett 5bd1718bb2 try non-static const to make stretch build happy? 2021-07-21 19:41:42 +08:00
Oliver Jowett f3e498a62a Treat the magic agc setting as just another gain step.
The legacy -10 value is still supported for compatbility with old
configs, but new configs should just select an appropriate gain e.g.
60dB.

rtlsdr default gain continues to be the highest regular gain step (~ 49.6dB)
2021-07-19 17:34:45 +08:00
Oliver Jowett d4b3b03fe0 Try to rewrite old-style config files to new-style config files
on upgrade to 6.0. (Not extensively tested yet)

We do this for two reasons:

1) the config file layout is completely different, it's error-prone
and tedious to force the user to manually transfer their customizations
on upgrade;

2) if there are user modifications to the config file, an upgrade triggered
remotely via piaware will prefer to keep the original config file intact
rather than installing the new version, and the old version just won't
work correctly with the new infrastructure.
2021-07-19 15:50:55 +08:00
Oliver Jowett ec69b94544 Overhaul of /etc/default/dump1090-fa
Now we have specific config options for different features rather
than just a big list of command-line options. You can still provide
custom options via EXTRA_OPTIONS or OVERRIDE_OPTIONS.

Also adds adaptive gain settings, and a "slow cpu" setting which
can turn on cpu-reducing options automatically when a slower (armv6)
CPU is in use.
2021-07-19 15:50:55 +08:00
Oliver Jowett 3069f3d99f Set some sensible net flush defaults rather than relying on the default config file 2021-07-19 15:50:55 +08:00
Oliver Jowett 4cf8eb254e Report actual duty cycle on startup 2021-07-19 15:50:55 +08:00
Oliver Jowett be3c9930f1 Add --adaptive-duty-cycle option.
This makes the adaptive gain code only process some fraction of all samples,
rather than every sample. This helps a lot with CPU on slower machines.
We default to a 50% duty cycle to save some CPU without really affecting
the behavior much.

We split the one-second adaptive gain blocks into 20* 50ms "subblocks"
Each subblock is either entirely processed or not processed at all,
based on the configured duty cycle. (This means that the duty cycle
can only be specified in approx 5% increments, but that should be
fine)

For adaptive dynamic range, there's no further complications - we
just look at fewer samples to compute the noise floor.

For adaptive burst, we need to scale up the measured burst rate by
1/duty cycle to account for the samples that we didn't process. It's
also more likely to cause functional changes as it's quite possible
for a relatively small number of loud messages being missed to
affect the computed rate substantially. Not many options there other
than increasing the duty cycle when adaptive burst handling is wanted.
2021-07-19 15:50:55 +08:00
Oliver Jowett e0f7a33df4 Fix some case where adaptive_range_gain_limit would not be correctly decreased 2021-07-19 15:50:55 +08:00
wiedehopf 9e671a14e4
restrict overlay rendering to covered areas (reduce source load) (#137) 2021-07-15 15:46:30 -05:00
eric1tran 4e21610c50 Merge commit 'refs/pull/127/head' of github.com:flightaware/dump1090 into dev 2021-07-14 13:59:46 +00:00
Matthias Wirth 603da245bd restrict overlay rendering to covered areas (reduce source load) 2021-07-14 09:39:37 +02:00
Oliver Jowett 6e5f2595e0 Update starch to upstream commit f4b84e62d5747ff44cd468c4d8ca1626434378c0 2021-07-13 13:16:02 +08:00
Oliver Jowett 2480e5169c Use a starch implementation for the burst-detection sample counting loop. 2021-07-08 18:53:02 +08:00
Oliver Jowett 1cb4284e6c Move the --wisdom help somewhere more sensible 2021-07-08 18:46:48 +08:00
Oliver Jowett ac97423249 Misc adaptive gain changes:
Update adaptive gain control loop to handle interactions between burst detection and dynamic range control.

Internal doc updates & naming cleanups.

Stats tweaks.
2021-07-07 20:57:34 +08:00
Oliver Jowett fd8f2d77e1 Fix adaptive gain stats not getting set on stats_current -> zeros
appearing in stats output. Now we have a validity flag for the stats
members where we have to pick one value and not simply sum data.
2021-07-07 20:18:54 +08:00
Oliver Jowett b3172181d5 Use compat/compat.h for endian-swapping functions in DSP code.
Might fix #128
2021-07-07 11:26:41 +08:00
Oliver Jowett 56625449e8
Adaptive gain, first pass (#134)
This PR adds basic adaptive gain support, which adjusts SDR gain on the fly based on the noise & signal levels seen.

There are two control mechanisms:

Dynamic range control is enabled by the --adaptive-range option. This adjusts SDR gain to try to achieve a minimum dynamic range, regardless of the exact hardware in the RF path.

Burst (loud message) control is enabled by the --adaptive-burst option. This decreases SDR gain when undecodable loud messages are heard, allowing for better reception of nearby aircraft at the expense of range.

This is only the basic implementation - see the PR for remaining work to do.
2021-06-29 20:11:13 +08:00
Eric Gideon b775f2b326 tweaks to group, mostly 2021-05-22 11:48:05 -07:00
Eric Gideon 8d877eeed8 further color cleanup, fixing links and headers in the settings box 2021-05-22 11:48:05 -07:00
Eric Gideon 88741d097b ol-layerswitcher pinned to global vars, adjusted margin/padding for consistent spacing 2021-05-22 11:48:05 -07:00
Eric Gideon 24c425c968 initial global vars added, BG color changed 2021-05-22 11:48:05 -07:00
Eric Gideon acde5b4a91 Prettier default-settings pass using 4 spaces for tabs to clean up CSS and enforce consistency 2021-05-22 11:48:05 -07:00
eric1tran f7b6f7aefc Merge branch 'dev' of github.com:flightaware/dump1090 into dev 2021-05-20 21:25:56 +00:00
Chris Carini a4cd5bb42d
Fixing spelling mistake in deprecated (#125) 2021-05-20 16:25:46 -05:00
eric1tran 465d436174 Fix ignored DisplayUnits in config.js PR #76 2021-05-20 17:29:17 +00:00
eric1tran 223283863f 6.0~dev 2021-05-18 20:41:27 +00:00
Oliver Jowett b4acf08738 Fix overflow in get_deadline for large (>2000ms) timeouts 2021-04-29 14:52:45 +08:00
Oliver Jowett 265055106b
Merge pull request #123 from VasiliyTurchenko/hackrf_ant_power
add "--enable-antenna-power" command line option for HackRF config
2021-03-22 18:52:18 +08:00
Турченко Василий Владимирович 80acb91dbc add "--enable-antenna-power" command line option for HackRF configuration
to be able to feed antenna's connector with +3.3v HackRF's internal DC
voltage.
2021-03-22 00:31:47 +03:00
Oliver Jowett 3d013c4251 Note that build profiles only work with buster 2021-03-22 00:36:11 +08:00
Oliver Jowett 86bb40a31c Update install docs to mention use of prepare-build.sh for package builds.
Soft removal of jessie support (just remove the build docs)
2021-03-22 00:33:03 +08:00
Oliver Jowett 8dd83d2e7e Don't hang on exit if rtlsdr hardware stops sending samples.
Give up and exit after 30 seconds of no sample data, rather than just warning and continuing.

background & discussion: https://discussions.flightaware.com/t/cpu-hikes-crash-dump1090-fa/74759

The scenario this addresses is:

 * Hardware wedges, USB bulk endpoint stops providing data
 * librtlsdr remains in rtlsdr_read_async() waiting for either USB data which never arrives,
   or a cancellation via _a different thread_ calling rtlsdr_cancel_async().
 * main thread notices the lack of SDR data and complains
 * something external e.g. piaware tries a restart and sends SIGTERM
 * the signal handler sets Modes.exit = 1; the main thread starts waiting for receive thread termination
 * because we're never getting callbacks from rtlsdr_read_async(), we never call rtlsdr_cancel_async
 * dump1090 hangs waiting on receive thread termination

To fix this, add a sdrStop() handler function where the general contract is "make the receive thread terminate".
In the rtlsdr case, this calls rtlsdr_cancel_async directly, which will make rtlsdr_read_async() return even
if the hardware is stuck.

The main thread then calls sdrStop() before waiting for receive thread termination.

Also, as discussed in the thread above, there's not really much point in continuing to run if the SDR
has wedged, so bail out after 30 seconds of no sample data.

Also, if pthread_timedjoin_np is available, use it in preference to pthread_join so that we do not wait
indefinitely for the receive thread on shutdown. If the join times out, give up and abort() as we can't
safely continue a clean shutdown while the receive thread is running.
2021-03-21 02:03:08 +08:00
Oliver Jowett c433463392 Reduce CPU further in --no-fix-df mode. Add --enable-df24 option.
This reinstates the fastpath in the 2.4MHz demodulator that
aborts message demodulation early if the DF bits don't match a message
type that we know how to decode, or stops early if the DF bits can
only correspond to a short 56-bit message.

Do this in a more general form where we test against a set of valid
DF values, rather than a switch/case. Then populate the sets based on
the current error-correction settings (e.g. if we are allowed to repair
DF damage with 1 bit error correction, then a DF17 message could appear
with any of DF=17, DF=16, DF=19, DF=21, DF=25, or DF=1 and still be
correctable to a valid DF17 message)

In the default case this produces a small CPU improvement as short
messages might be able to stop earlier and a few DF values can be ignored
early. With --no-fix-df it produces a larger improvement as relatively few
DF values are valid in that mode.

To further reduce CPU, the default behaviour has changed to _not_
decode DF24 messages (Comm-D ELM messages). These are rarely seen in
the wild and dump1090 can't do anything useful with them. Disabling
them allows us to further reduce the set of valid DF values as they
effectively use all DF values from 24..31, 25% of all possible values.
To re-enable DF24 decoding, use the new `--enable-df24` option.

Finally, avoid doing some CRC calculations twice. This was only happening
once per valid decoded message, not per demodulation attempt, so it's not
such a large win.
2021-03-19 17:03:15 +08:00
Oliver Jowett 455896e86d Fix broken 32-bit x86 test that broke builds on non-x86 2021-03-17 02:21:18 +08:00
eric1tran 037fe4f37f Remove extra <td> tag 2021-03-15 12:35:12 +00:00
Oliver Jowett c97b83d3ed Maybe fix alignment warnings in arm neon code with recent gcc 2021-03-13 20:24:01 +08:00
Oliver Jowett 462dee56f3 Fix builds on 32-bit x86 2021-03-13 12:49:40 +08:00
Oliver Jowett d3c692f630 5.1~dev for the dev branch 2021-03-13 12:41:21 +08:00
eric1tran f862b530c8 Release 5.0 2021-03-11 13:08:06 +00:00
eric1tran 740d73ac71 Merge branch 'dev' into staging 2021-03-09 21:14:27 +00:00
eric1tran 2a62c514f1 Don't show button to stats page if there's an issue getting the link 2021-03-09 18:47:27 +00:00
eric1tran fe91fbc3a4 Bump css version 2021-03-09 08:30:19 +00:00
eric1tran bd3ec0cbdc Merge branch 'dev' into staging 2021-03-09 05:34:55 +00:00
eric1tran 988489fae1 Fix invalid inline CSS in new SkyAware map 2021-03-09 05:31:32 +00:00
Emilien Klein 63df5a262d
Fix invalid inline CSS (#117) 2021-03-08 23:28:52 -06:00
eric1tran e7f9401722 Fix postinst file 2021-03-08 22:59:09 +00:00
eric1tran f9e252c110 Bannner showing the dump1090-fa link will soon be decpreated 2021-03-08 20:12:29 +00:00
eric1tran e7d39c9abb Enable skyaware module in postinst file 2021-03-08 19:29:41 +00:00
eric1tran 2c47717360 Have separate map url for new merged SkyAware. Set default port 8080 to this map 2021-03-08 18:23:20 +00:00
eric1tran 047c193da6 Hide 1090 labels if dump1090 is not enabled 2021-03-08 15:28:39 +00:00
eric1tran bd43fec71e Bug in last commit 2021-03-08 15:21:37 +00:00
Paul Philippov cb25eb2cb8
Update README.md (#92)
Additionally requires fakeroot on a newly installed Debian.
2021-03-08 16:39:37 +08:00
Oliver Jowett f36a0c6d38 More changelog 2021-03-08 16:37:19 +08:00
VasiliyTurchenko 9c2531a98d
fixed screen (first line) issue when in the interactive mode (#116) 2021-03-08 16:34:56 +08:00
Oliver Jowett db53a09dbf Changelog updates 2021-03-08 16:28:07 +08:00
Oliver Jowett 9c67290562 Fix stray '+' in interactive mode when distance mode isn't enabled 2021-03-08 15:40:11 +08:00
Oliver Jowett 005e3db2ba Fix suggestion for --aggressive replacement 2021-03-08 15:37:42 +08:00
Oliver Jowett 1653ce9ca2 Update json docs for messages_by_df, new interval options. Remove
old references to the internal webserver.
2021-03-08 15:25:31 +08:00
Oliver Jowett a75296ae72 Reduce `make wisdom.local` iterations to match `generate-wisdom` 2021-03-08 15:18:35 +08:00
Oliver Jowett 1c7db21349 Add docs about generating starch wisdom files 2021-03-08 15:06:15 +08:00
Oliver Jowett a135d2b915 Add a --no-fix-df option
Usually, all message candidates are speculatively corrected as if
they were DF11/17/18, even if the DF field has a different value. This
allows correction of messages when there is correctable damage to the
DF field.

However, running every message candidate through a couple of CRC checks
is expensive, CPU-wise, when decoding messages off the air, as there are
a large number of message candidates that are actually just junk data, and
computing CRCs for all of those adds up. The --no-fix-df option allows
disabling this sort of correction. The tradeoff is that messages with
damage to the DF field will not be corrected.
2021-03-08 14:23:35 +08:00
eric1tran 29d6569ee3 Merge branch 'dev' into staging 2021-03-07 05:07:59 +00:00
eric1tran d90426e1ce Bump script cache bust version to 5.0 2021-03-07 04:25:09 +00:00
eric1tran 408a3e617a Bump version to 5 2021-03-05 13:22:02 +00:00
eric1tran a59af7385c Update aircraft db to 20210305 2021-03-05 06:02:35 +00:00
eric1tran 5db6efd62d Ignore messages heard on 1090 when we hear them on 978. We will support multiple datasource display in a later release 2021-03-03 20:15:50 +00:00
eric1tran 77ab9f04ba Hide UAT toggle check box if disabled 2021-02-25 19:06:16 +00:00
eric1tran e8fe48485e Change styling for registration numbers that are used as idents. Hide UAT message rate if UAT is disabled. 2021-02-25 15:42:16 +00:00
eric1tran e23cd7e73b Use /data for 1090 directory to avoid breaking exisiting tools like dump1090exporter that may be looking there 2021-02-25 06:00:43 +00:00
eric1tran 74b1a39aa0 Merge 1090 and UAT aircraft into one map
Squashed commit of the following:

commit ef61cba13698090b85fea3136bc77e320eab3d0d
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 04:39:22 2021 +0000

    Remove unused receiver clock code

commit 809cf656b5a098948fbfc5ce2b5f60f753fb4043
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 04:35:32 2021 +0000

    Avoid calling getDataSource() so many times and cleanup spacing

commit a0000b942bb5aa5f8061db0ca9d405461c6eea07
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 04:19:11 2021 +0000

    Copy paste bug

commit ccc3cd3964bddcd86e8faf45c06e577309cffb02
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 04:17:14 2021 +0000

    Filter UAT logic

commit 34dc860a16e1c57cdc3563ec31c45f9b1b133d4c
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 03:24:56 2021 +0000

    Reorder message rate text

commit 25db80799a2a6dc8e33835cb2ed43c305c87a4d8
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 00:56:43 2021 +0000

    Track 1090 and 978 message rate separately

commit a2031d13e4a447ad0f8de61eada75f0da019d1c2
Author: eric1tran <eric1tran@gmail.com>
Date:   Thu Feb 25 00:27:25 2021 +0000

    UAT classification logic

commit 5482274016eecfbc27f2b5de6779c032803ca177
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 23:13:39 2021 +0000

    Spacing

commit 2fc4408e6437ec5e0db2329d46a68fc6538abc45
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 22:57:05 2021 +0000

    Load UAT history.json files if UAT is enabled

commit 9ccf4eba7590b1f38c78aeb73209b48cb8e0c34f
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 22:24:23 2021 +0000

    ajax calls to fetch UAT aircraft json if enabled

commit d8f0c1c042bdba8ae1348a513df7dcca6ebc23fc
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 21:29:01 2021 +0000

    Read skyaware978 config files on initialization

commit 0245fa7449e92555b7631ab0365e43fb38e1c221
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 20:15:09 2021 +0000

    Change SkyAware url to /skyaware to genericize it for dual mode

commit 9384364b2473f8c73d3f165d7f5192c1995457a5
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 19:46:06 2021 +0000

    Add UAT toggle and description (non-functional)

commit 9b65a55c0ceb7c3da3b3515d26f0d5d42192f658
Author: eric1tran <eric1tran@gmail.com>
Date:   Wed Feb 24 19:32:54 2021 +0000

    Removed unused css
2021-02-25 05:43:10 +00:00
eric1tran 9f07a81dfa Bump faup1090 version to 8E 2021-02-24 19:21:26 +00:00
eric1tran ff7aafe0bb Aircraft label styling 2021-02-24 16:34:57 +00:00
eric1tran c23438a5cf Adjust aircraft label outline width 2021-02-22 22:13:59 +00:00
eric1tran b84f427732 Remove unused class var 2021-02-22 21:59:36 +00:00
eric1tran 3773acf4c0 Null check before setting aircraft icon style 2021-02-22 21:57:32 +00:00
eric1tran e111303b1e Implement toggle checkbox to show/hide aircraft labels 2021-02-22 17:37:00 +00:00
eric1tran 45e13b20ba Add aircraft labels on icons and a non-functional checkbox to toggle the labels 2021-02-22 17:02:20 +00:00
Oliver Jowett 22d21cd013 Rework the interactive-mode Mode column to show more detail.
New Mode values:

S:  Mode S, no ADS-B
A0: ADS-B v0, DO-260
A1: ADS-B v1, DO-260A
A2: ADS-B v2, DO-260B
NT: ADS-B non-transponder
R:  ADS-R
T:  TIS-B
2021-02-18 14:20:44 +08:00
Oliver Jowett 3324f072cd Set an up to date message timestamp when refreshing interactive mode, just
in case.
2021-02-18 14:02:54 +08:00
Oliver Jowett 5a33b4ee8f Set at least airground = AG_UNCERTAIN for airborne position messages with valid altitudes.
DF18 messages don't have a CA field so we can't set airground from that.
That meant that aircraft tracking wouldn't update airground state at all from a DF18
airborne position message, even if the existing tracked airground state was stale.
It seems reasonable to set at least AG_UNCERTAIN if we're seeing airborne positions
with valid altitude data.

Fixes github issue #113
2021-02-18 13:57:27 +08:00
eric1tran d8d5f2a117 Change button color on filter set 2021-02-10 20:40:57 +00:00
Oliver Jowett 33bb2d929b Mark cpu_features and starch as vendored code 2021-02-10 14:12:26 +08:00
Oliver Jowett d1f6d02e9a Try to handle generated starch output more sensibly in merges & github compare mode 2021-02-10 13:58:14 +08:00
Jurre Van Wouw c4e346698e
Add NetBSD detection to Makefile; use NetBSD's curses (simply called curses) rather than ncurses on NetBSD (#111) 2021-02-10 12:44:30 +08:00
eric1tran 4eab12497e Update filter slider default values accordingly when changing the DisplayUnits 2021-02-10 01:06:35 +00:00
Eric Tran b7205e2e64
faup1090 changes to consume commands via stdin (#107)
* Create a network service and connection faup's stdin. Create a Modes.faup_rate_multiplier attribute and set from faup command input

* Use faup_rate_multiplier to adjust the minAge for emitting messages

* Convert upload_rate_multiplier to a double and adjust minAge with it

* Cleanup

* Var name change

* MODES_NOTUSED define for unused modes client object

* Sanity check on faup multiplier field
2021-02-09 07:25:51 -06:00
Oliver Jowett c421c31152 Overhaul of message scoring & error correction.
Major changes:

Try to error-correct all messages that potentially could be DF11/17/18
even if the original DF value is different. This allows messages with
correctable damage in the first 5 bits to be correctable.

Track recently-seen DF18 addresses separately to DF17 addresses.
DF18 does not imply Mode S support, so we don't want to treat it like
a known Mode S emitter, but once we've heard some DF18 for an aircraft
we can be more confident about future DF18 messages for the same
address.

Rework the scoring system so it's just a big enum that lists all the
possible outcomes in the order that we want. This makes the relative
ordering of different messages clearer, and makes it easier to move
messages above/below the accept thresholds as needed.

Don't accept 2-bit-error-corrected messages that are from aircraft we
have not previously seen. This greatly reduces the number of garbage
messages when using 2-bit error correction.

Overall results are:

 * more CPU required for decoding (approx 30% increase in my tests)
   as we're doing a lot more speculative CRC-checking work
 * no significant change to message rates with error correction off
 * about 5% more 1-bit-corrected DF17 decodes, with a
   disproportionate increase in those messages contributing to
   successful position decodes / unique aircraft counts
 * _fewer_ decodes with 2-bit correction (versus old code with 2-bit
   correction), but the message quality is substantially improved,
   the rate of garbage decodes / phantom aircraft is greatly reduced

sample stats:

1-bit correction, old code:
    141158 total usable messages
    137852 accepted with correct CRC
      3306 accepted with 1-bit error repaired
     27446 DF17 messages
        51 unique aircraft tracks

1-bit correction, new code:
    141296 total usable messages
    137854 accepted with correct CRC
      3442 accepted with 1-bit error repaired
     27528 DF17 messages
        55 unique aircraft tracks

2-bit correction, old code:
    142656 total usable messages
    137809 accepted with correct CRC
      3283 accepted with 1-bit error repaired
      1564 accepted with 2-bit error repaired
     28803 DF17 messages
       349 unique aircraft tracks (<- note that most of these are garbage)

2-bit correction, new code:
    142426 total usable messages
    137822 accepted with correct CRC
      3420 accepted with 1-bit error repaired
      1184 accepted with 2-bit error repaired
     28666 DF17 messages
        55 unique aircraft tracks
2021-02-09 20:10:55 +08:00
Oliver Jowett 132702cfa7 Regenerate starch-generated code for starch update & aarch64 wisdom 2021-02-09 14:16:12 +08:00
Oliver Jowett 40c24b1c55 Add temporary wisdom.aarch64 2021-02-09 14:15:05 +08:00
Oliver Jowett 5600d3fc71
Merge pull request #108 from gtjoseph/dev-fa-starch-aarch64
Starch config: Add aarch64
2021-02-09 14:08:52 +08:00
Oliver Jowett fa80e7c917 Update starch to upstream commit f76162205fa082d4c9a75b89eb4295e03f5f68fd 2021-02-09 14:05:05 +08:00
eric1tran 270c629515 Italicize filter count text 2021-02-09 04:42:02 +00:00
eric1tran 8c892973be Merge branch 'dev' of github.com:flightaware/dump1090 into dev 2021-02-09 04:33:57 +00:00
eric1tran d5184efa6e Display a count of active filters 2021-02-09 04:33:50 +00:00
eric1tran c2e1c1f6d5 Rearrage My ADS-B Stats page button 2021-02-08 20:14:45 +00:00
George Joseph 2308c1d196 Starch: Changed aarch64 flavor to use simd
The flavor is now armv8_neon_simd
2021-02-08 10:10:44 -07:00
Oliver Jowett d8cca659e7 Remove stray extra cpufeatures makefile include 2021-02-09 00:30:25 +08:00
Oliver Jowett 4ad6c7b4d3 Disable non-generic starch build on stretch/jessie 2021-02-08 23:55:57 +08:00
George Joseph 1b0bcefae6 Starch config: Add aarch64
* Added aarch64 to dsp/starchgen.py and Makefile.
* Regenerated files
2021-02-07 17:08:53 -07:00
Oliver Jowett 1b1f9de119 Increase default stats json buffer size to 8k. Retry with a larger buffer if we run out of space, like we do with aircraft.json
With the addition of the per-DF stats, the stats output started to exceed 4k in some cases (notably, you need --net turned on).

Fixes #106
2021-02-07 22:22:01 +08:00
eric1tran 0aedcffc5b Version changes to 5.0~dev 2021-02-07 01:26:43 +00:00
Oliver Jowett 2e59e8f1d6 magnitude_power_uc8_benchmark: don't rely on a previous benchmark including <math.h>
Fixes #105
2021-02-05 14:36:06 +08:00
Oliver Jowett d1fc00a273 Write final stats.json on exit 2021-02-04 16:36:13 +08:00
Oliver Jowett 6a11387861 Collect stats on messages received by DF type 2021-02-04 16:33:26 +08:00
Oliver Jowett 11fb727325 Don't run track / filter expiry if reading recorded captures via --ifile 2021-02-04 16:28:46 +08:00
Oliver Jowett 5782ad7468 Fix a stupid fifo bug that would orphan enqueued data.
This magically didn't really affect normal operation, because in
normal operation the demodulator can consume data faster than it
is produced, so the fifo never grows beyond 0-1 items.

However in cases where the demodulator is slow and the producer
is fast (e.g. reading from a file and running with lots of debug on)
the fifo would lose buffers as soon as it had more than one pending.
2021-02-02 17:51:25 +08:00
Oliver Jowett fdc1ac731d Update starch to upstream commit 521d7632a1076733030017a571facd1cd304e669 2021-02-02 11:34:37 +08:00
Oliver Jowett 2c7b331352 Pass literal type names to STARCH_BENCHMARK_ALLOC (fixes #103) 2021-02-02 11:13:35 +08:00
Oliver Jowett f1c576b657 Support --stats-every with intervals <60 seconds. Add --json-stats-every option
Previously, json stats updates were fixed to 60 seconds, and using --stats--every
with an interval less than 60 seconds produced confusing results.

This commit fixes --stats-every with short intervals, and adds --json-stats-every
to control the json stats update interval. Note that if --json-stats-every is not
a multiple of 60 seconds, then the 1-/5-/15-minute data may not include all data
up to the current time (in that case, the most recent data is reflected in
the "latest" stats)

This implements the alternative approach discussed in PR #89
2021-02-01 15:18:42 +08:00
Oliver Jowett 490b5ce36f Clean up generateStatsJson error handling a bit 2021-02-01 14:07:00 +08:00
Oliver Jowett ab7aa856bc Make stats display fixed-width.
The numbers displayed on the stats output were also very hard to
keep track of because the display widths kept changing depending
on the value.  They are now displayed with fixed widths.

(courtesy @gtjoseph)
(cherry picked from commit 19decfee0cef5f9a93a533f45f072cb1b0a6da2a)
2021-02-01 12:52:01 +08:00
Oliver Jowett 5e8be14f2e
Merge pull request #99 from MavEtJu/fix-interactive-ttl
Fix interactive mode alignment of Time when TTL is > 99
2021-02-01 11:56:01 +08:00
Oliver Jowett 2ea75a345d fix merge indentation 2021-02-01 11:50:43 +08:00
Oliver Jowett 1eab1fc04b
Merge branch 'dev' into fix-interactive-ttl 2021-02-01 11:48:07 +08:00
Oliver Jowett dbdf18dcc0 Increase alignment requirements of uc8_t to avoid warnings when interpreting as uint16_t 2021-02-01 11:26:39 +08:00
Oliver Jowett 3eb2783cdf Use abs, not fabs, on integer types 2021-02-01 11:25:23 +08:00
Edwin Groothuis c06c697e26 When using a --interactive-ttl of more than 99, the alignment
didn't work out.
2021-01-23 17:48:49 +11:00
Oliver Jowett bff71dc820
Move all converters to starch-based implementations (#97)
* Switch all conversion routines to use starch.

main user-visible changes:

 * ensure you check out submodules ('git clone --recurse-submodules")
 * --version shows the CPU features and DSP implementations in use
 * --wisdom allows overriding of the built-in architecture wisdom
 * --dcfilter no longer supported
 * "starch-benchmark" binary will benchmark all options on the
   current machine and can produce a wisdom file to feed to
   the --wisdom option

If you have a usecase for --dcfilter, please get in touch and
let me know - it's an edge case and for now there's no starch/DSP
support for it, but support can be written if needed.

In almost all cases the new conversion routines are slightly or
substantially faster than the old conversion routines. The only case
that is slower is SC16/SC16Q11 on a Pi 0, which is around 10% slower
due to changing from heavily approximated lookup tables to higher
quality results (but SC16 is probably already out of reach of a Pi 0)

* No need to build with SC16Q11_TABLE_BITS any more

* Add oneoff/uc8_capture_stats

(reads a UC8 capture; measures min/max/mean I and Q)

* Switch UC8 conversion to 127.4 center, 128 range.

Looking at actual UC8 captures from a RTL2832, the mean I and Q
are actually at 127.4, so use that as the zero point.

This means that the resulting I/Q maximum values could be as large as
127.6. Switch to 128 for simplicity.

* Switch to the new UC8 zero offset in benchmarks, fix some bugs

* Fix some bugs in SC16/SC16Q11 validation, tighten the max error requirements

* Ditch UC8 approximation path, add a NEON VRQSQRTE path.

* Tweak the SC16 exact path, add a new impl that uses a mix of
u32 & floats.

* SC16Q11 impl tweaks:

 * add a u32->float exact path
 * ditch the approximation path
 * add a NEON VRSQRTE path
 * add a 12-bit table path (using the full signed I/Q value, not absolute value)

* Ditch SC16 approximation path, add NEON vrsqrte path

* Add oneoff/dsp_error_measurement

This runs sample input through the DSP functions that are
allowed to be inexact and dumps the results as a TSV suitable for
feeding to gnuplot to look at the actual errors.

* Update make clean, make wisdom targets

* Update wisdom based on benchmarking

* Preserve the raw wisdom benchmark data

* Update to latest starch

* Update .gitignore for new wisdom files

* Update starch generated code

* Build starch-benchmark as part of the 'all' target

* Use wisdom from /etc/dump1090-fa/wisdom.local if present

* Package starch-benchmark and a helper script to generate local wisdom data

* Remove submodules in preparation for importing them directly

* Import cpu_features v0.6.0 from https://github.com/google/cpu_features/releases/tag/v0.6.0

* Import starch at commit a725c8491dc33a321565d451b385131e589d8490
from https://github.com/flightaware/starch
2021-01-21 19:45:00 +08:00
Oliver Jowett c7675b3cd1 Add missed expiry code for emergency / nac_v fields; initialize emergency_valid.
(noticed by @wiedehopf)

Fixes #96
2021-01-15 18:20:50 +08:00
eric1tran b3fcf82473 Merge branch 'filter_enhancements' into dev 2021-01-08 17:31:53 +00:00
Oliver Jowett e8adeb3414 Fix double-counting of overlap samples in stats. 2021-01-05 19:25:44 +08:00
eric1tran 8c325e04a0 Fix up long decimal issue for min/max altitude values 2020-12-14 23:24:45 +00:00
eric1tran 3577cb4057 Adjust max altitude filter to 65000 2020-12-14 19:56:51 +00:00
eric1tran 9950e72d1a Fix minimum width of sidebar and more spacing cleanup 2020-12-14 16:39:34 +00:00
eric1tran 8f9abe57be Add noUiSlider js files 2020-12-14 16:03:07 +00:00
eric1tran 930d2534a2 Speed filter and white space cleanup 2020-12-14 14:37:16 +00:00
eric1tran 22e02dbc62 noUiSlider for altitude filtering plus other styling 2020-12-14 06:34:40 +00:00
eric1tran af4951a494 Merge branch 'additional_filtering' into dev 2020-12-11 16:58:13 +00:00
eric1tran ea5a2b8740 Set button to take you to claim url if the feeder is not claimed 2020-12-11 16:56:48 +00:00
eric1tran a0dc843842 Add a button that will take you your My ADS-B Stats page if claimed 2020-12-11 16:42:24 +00:00
eric1tran 16b3d12670 Keep configuration buttons highlighted while active and some styling 2020-12-10 00:55:00 +00:00
eric1tran 829fe1b5e2 Filter and Column buttons to expand panels and styling cleanup 2020-12-09 23:34:32 +00:00
eric1tran 47e4df2b7b Put filters into an accordion style dropdown 2020-12-09 18:22:15 +00:00
eric1tran 1916fc6648 Use regex match for filter comparisons 2020-12-09 15:18:05 +00:00
eric1tran ad56c1363b Include SkyAware in version display 2020-12-08 20:44:14 +00:00
eric1tran 9b85a30c91 Enable all data source checkboxes by default 2020-12-08 20:34:04 +00:00
eric1tran cd6d3a373b Comments and spacing 2020-12-08 17:24:10 +00:00
eric1tran c466a4724f Add filtering on data source 2020-12-08 17:24:10 +00:00
eric1tran e2b2ce3f63 Add checkboxes next to data source legend and css styling 2020-12-08 17:24:10 +00:00
eric1tran d3459b1697 Adding filtering by aircraft ident 2020-12-08 17:24:10 +00:00
eric1tran 0fddde5126 Make aircraft type filter case insensitive 2020-12-08 17:24:10 +00:00
eric1tran f4f2f3ddad Add filtering by aircraft type 2020-12-08 17:24:09 +00:00
Oliver Jowett c1eeda612e fifo_acquire / fifo_dequeue: maybe fix pthread_cond_timedwait error handling
It was possible, due to an off-by-one error in normalize_timespec, that
the computed deadline passed to pthread_cond_timedwait had tv_nsec == 1000000000.
glibc would reject this with EINVAL. While I never caught this in the act, there
seem to be two follow-on problems from this:

1) we were looking for a negative return from pthread_cond_timedwait and testing errno.
This is not how errors are reported, instead pthread functions return the error value
directly. So the enclosing loop could spin forever, repeatedly passing the bad deadline
value.

2) even if the error handling caught the EINVAL return, it assumed that the mutex was
no longer held and didn't release it; but on error returns, the mutex state is actually
untouched.

Fix both cases (probably), and log about unusual returns from pthread_cond_timedwait
2020-11-17 19:59:59 +08:00
Oliver Jowett 5c043e8496 normalize_timespec: handle tv_nsec == 1000000000 correctly 2020-11-17 19:59:47 +08:00
Eric Tran e48006311b Fix type on SkyAware README 2020-10-12 03:08:41 +00:00
Oliver Jowett f0055c978d Avoid false positives for address 000000 in the icao filter hashtable 2020-10-08 19:30:06 +08:00
Eric Tran 66f26846b8 Merge branch 'master' into dev 2020-10-02 16:36:11 +00:00
MAUGIN Thomas 9fb1e5b9e8
fix(html): add empty coordinates to constructor (#82)
- Change LineString constructor creation, see deprecated null constructor https://github.com/openlayers/openlayers/blob/main/changelog/upgrade-notes.md#v510
2020-10-02 10:52:51 -05:00
Eric Tran 4cde98e063
Fix up SkyAware README 2020-10-01 09:36:46 -05:00
Oliver Jowett c3cd1ec0de limesdr: use --gain (in dB) if --limesdr-gain was not specified 2020-10-01 13:53:50 +08:00
Oliver Jowett 016cb8f9d2
Merge pull request #81 from gtjoseph/dev-for-fa
Interactive mode updates
2020-10-01 00:47:42 -05:00
Oliver Jowett dc2f47796c 4.1~dev for the dev branch 2020-10-01 13:46:22 +08:00
Eric Tran e00935c8d2
SkyAware README 2020-09-29 22:53:34 -05:00
George Joseph 68e95c06cc Interactive mode updates
These updates were designed to assist those using interactive
mode to tune antennas and SDR gain.

* Add options to display distance and bearing in interactive mode

  Distance and bearing instead of latitude and longitude can now be
  displayed in interactive mode using the following options to
  dump1090-fa and view1090-fa.

  --interactive-show-distance   Show aircraft distance and bearing
                                instead of aircraft lat/lon
                                (requires --lat and --lon)
  --interactive-distance-units  Distance units ('km', 'sm', 'nm')
                                (default: 'nm')"

  You have to specify a reference --lat and --lon for this to
  work of course.

* A new line now shows at the top of the interactive display that
  has for the current sample:

  Total valid aircraft count
  Vidible aircraft count
     Will be less than total if the screen hasn't enough lines to show
     them all.
  Max RSSI
  Min RSSI
  Mean RSSI
  Max Distance

 Tot:  47 Vis:  47 RSSI: Max 25.4+ Mean -29.5 Min -36.9-  MaxD:  197.3nm+

* Add max distance and min/max RSSI indicators

  A '+' after the distance in a row indicates it's the row with the
  maximum distance.

  A '+' after the RSSI in a row indicates it's the row with the highest
  RSSI.

  A '-' after the RSSI in a row indicates it's the row with the lowest
  RSSI.

  The summary line at the top of the screen always shows the values for
  ALL aircraft, even those not visible.  The row indicators only mark
  visible rows though.

  In this example, the first aircraft is both the farthest away and has
  the weakest RSSI.  The second aircraft has the strongest RSSI.

 Tot:  47 Vis:  47 RSSI: Max 25.4+ Mean -29.5 Min -36.9-  MaxD:  197.3nm+     -
 Hex    Mode  Sqwk  Flight   Alt    Spd  Hdg  Dist(nm) Bearing  RSSI  Msgs  Ti
────────────────────────────────────────────────────────────────────────────────
 A8D5A4 S2                   34000  438  252   197.3+      85  -36.1-   26  2
 A39A13 S2ac  5740  FFT525   30750  439  256    98.8       68  -25.4+  123  0
 A70B23 S2ac  2744  LXJ553   43000  419  258   136.1       39  -33.6   174  0

* Finally, a new option '--interactive-callsign-filter' has been added
  to allow filtering interactive by callsign.  The value can be a
  simple string, in which case aircraft with that string anywhere in its
  callsign will be displayed, or a regular expression should you want a
  more precise match.

  Examples:
    --interactive-callsign-filter UAL
      will match all aircraft with UAL anywhere in its callsign.
    --interactive-callsign-filter "^UAL"
      will match only those callsigns that start with UAL.
    --interactive-callsign-filter "^(UAL|AAL)"
      will match only those callsigns that start with UAL or AAL.
    --interactive-callsign-filter "^N[0-9]" or "^N[[:digit:]]"
      will match only those callsigns that start with "N" and a number

  If you need more info on regular expressions, see this link:
  https://en.wikipedia.org/wiki/Regular_expression
2020-09-29 06:23:55 -06:00
Eric Tran 4f5f637dc1 Changelog edits 2020-09-24 15:39:52 +00:00
Eric Tran 863694761a Release 4.0 and update changelog 2020-09-24 15:31:52 +00:00
Eric Tran 3167459bfc Update README with current compressed csv file 2020-09-24 06:10:58 +00:00
Eric Tran 398728439b Update aircraft db to 20200924 2020-09-24 06:01:36 +00:00
eric1tran be9174a352 Bump script cache bust version 2020-09-23 13:03:08 -05:00
Eric Tran ff190286a6 Bump version to 4.0~dev 2020-09-21 15:31:46 +00:00
eric1tran 14ccaa93bd
README.md for geojson directory 2020-09-11 21:40:49 -05:00
Oliver Jowett 774c3cdd55
Merge pull request #79 from b3nn0/dev
Forward MLAT traffic to Stratux JSON output, marked with IsMlat:true in JSON
2020-09-11 21:16:01 -05:00
Eric Tran 24e58762b5 Remove dump1090.deb reference in Jenkinsfile breaking builds 2020-09-11 22:12:24 +00:00
Adrian Batzill 6714148c45 Forward MLAT traffic to Stratux JSON output, marked with IsMlat:true value in JSON 2020-09-10 10:20:21 +02:00
Oliver Jowett 6a4a239d0f
Merge pull request #78 from Gluttton/fix_trivial_typo
fix a trivial copy-paste typo in comments
2020-09-08 10:44:13 -05:00
Oliver Jowett 418e13e6b6 Merge PR #61 (Stratux output format support) plus fixes 2020-09-08 23:36:34 +08:00
Oliver Jowett 303dcc9915 Fix stratux output timestamps to really be UTC as they claim 2020-09-08 23:35:17 +08:00
Oliver Jowett 7356676c5b Don't need conditional output on the stratux port, that's done in prepareWrite() 2020-09-08 23:30:24 +08:00
Oliver Jowett 9b06099971 Enable net mode on bare stratux port option 2020-09-08 23:25:01 +08:00
Oliver Jowett da3e9766de Harden the stratux output a bit: use safe_snprintf, jsonEscapeString 2020-09-08 23:22:53 +08:00
Oliver Jowett ec90edcd8d Simpify stratux service init 2020-09-08 23:21:34 +08:00
Oliver Jowett bc9336e0be Revert "forward mlat messages to Stratux"
This reverts commit c89930b4b9.
2020-09-08 23:10:18 +08:00
Oliver Jowett 917aa6a0e2 Merge branch 'stratux' of https://github.com/Determinant/dump1090-fa-stratux into Determinant-stratux 2020-09-08 23:08:37 +08:00
Determinant c89930b4b9
forward mlat messages to Stratux 2020-09-07 15:36:34 -04:00
Gluttton 992f036fc2 fix a trivial copy-paste typo in comments
Signed-off-by: Gluttton <gluttton@ukr.net>
2020-08-31 22:53:14 +03:00
Determinant d25103361a
make change according to the suggestions 2020-08-30 21:21:49 -04:00
eric1tran ee552eb058 Fix capitalization 2020-08-28 10:45:33 -05:00
Oliver Jowett 1dbb8ab234 Expose modea_hit / modec_hit in aircraft.json 2020-08-24 15:03:17 +08:00
Oliver Jowett fba10d3262 Update FreeBSD instructions to use pkg not ports for pkgconf 2020-08-24 14:15:09 +08:00
eric1tran 798c0a3fa5 Enable and add more map layers 2020-08-19 19:58:51 +00:00
Oliver Jowett 1d3e5c03e9 More _WIN32 ifdef pruning 2020-08-11 13:51:16 +08:00
Oliver Jowett ddce32849d Tweak --net behaviour to simplify using a subset of network ports.
This tries to retain the existing behaviour of --net / --net-only
while making it easier to say "listen on only these specific ports".

If --net or --net-only is specified, network mode is enabled and
default port values are assumed for any port not otherwise specified
on the command line. Specifying a port of 0 disables that port. This
is the same as the old behavior.

If --net or --net-only is not specified, but at least one
of the --net-xxx-port options is specified, then network mode is
enabled with no default port value and only those ports explicitly
configured on the command line are used.

This means you can e.g. configure a port-30005-only SDR receiver
by specifying just "--net-bo-port 30005"; or configure a
network-receive-only receiver (e.g. for SkyAware display) by
"--device-type none --net-bi-port 30004,30104". These were possible
previously but required turning off a lot of the default ports.
2020-08-11 13:44:39 +08:00
Oliver Jowett 1d04174f37 Update macos build notes 2020-08-11 13:15:41 +08:00
Oliver Jowett e00d12f817 Update README for FreeBSD build notes. 2020-08-11 13:04:53 +08:00
Oliver Jowett 10b9bc6614 Handle builds with no SDR support better.
Reorder --ifile pseudo-sdr after the "none" SDR so that a build with no real
SDR support defaults to "none" not --ifile

If the "none" SDR was selected and network mode is not enabled, tell the
user about the problem rather than just failing to do anything useful.
2020-08-11 12:55:17 +08:00
Oliver Jowett 9237086b38 Fix on-exit memory leaks noticed by @Mictronics 2020-08-10 15:00:25 +08:00
eric1tran da3557fcfe Put aircraft count before page title 2020-08-09 00:33:59 -05:00
Assaf Sapir d353568c59
Fix MessageRate might be null and remove unused config (#71)
* Fix MessageRate might be null && unused config

* Page title edits

Co-authored-by: Eric Tran <eric1tran@gmail.com>
2020-08-08 18:26:57 -05:00
sigwx a0b0038df7
Control map via URL options (#58)
* Add URL options to hide different aspects of the default display, helpful for starting for a kiosk

* Fix spacing in changes

* More options to move map left/right/up/down

* Allow movement in all directions, consolidate some code

* Add controls for units and range rings from url

* Swap left/right,up/down behavior for map moves

* Convert #nohistory anchor tag to a query param like the other parameters. Make query parameters values explicitly state true

* Fix for enableRings so it will toggle the setting

* Use show/hide parameter values to avoid having a a showX/hideX parameter for each option, Rename some parameters, resize map when hiding banner/sidebar, cleanup

Co-authored-by: BuildTools <unconfigured@null.spigotmc.org>
Co-authored-by: eric1tran <eric1tran@gmail.com>
2020-08-07 13:47:32 -05:00
Oliver Jowett af1f4f84a9 Merge PR #38 - OSX/FreeBSD/OpenBSD portabilty.
This is minimally tested on OSX, and not at all on *BSD.
Since I did some cleanups in the compat code without testing on *BSD,
it could well be broken there.

This may also fix #33 as #38 included those changes.
2020-08-07 15:09:22 +08:00
Oliver Jowett 286a6301f8 Try to clean up the compat stuff a bit 2020-08-07 15:08:45 +08:00
Oliver Jowett 74e11bd26f Reinstate the freebsd pkg-config workaround in another form 2020-08-07 14:43:44 +08:00
Oliver Jowett c3017cc0a4 bladerf seems to compile OK on osx, add it to the readme 2020-08-07 14:34:25 +08:00
Oliver Jowett 799b568dfb Add le64toh to compat.h for bladerf support on osx 2020-08-07 14:32:51 +08:00
Oliver Jowett 1174841f71 Fix merge conflicts, clean up the Makefile 2020-08-07 14:30:54 +08:00
Oliver Jowett 5a30efb137 Try to make the README a bit more up to date 2020-08-06 14:07:57 +08:00
Oliver Jowett c8d96acbdc Add support for custom builds that don't include all SDRs, to
reduce dependency requirements a little.

(Ideally we'd have some sort of module system here, and split
the dependencies out nicely into separate packages, but that's a
problem for other day; for now I can live with custom packages
having the same name as the full build, since we'll never
distribute them ourselves)
2020-08-06 14:06:20 +08:00
Oliver Jowett 48af886e46 Update maintainer address, clean up the control file a bit. 2020-08-06 14:05:55 +08:00
Oliver Jowett efb4c1f60f Drop the very legacy dump1090 upgrade package, assume nobody is using those
ancient packages any more.
2020-08-06 14:03:47 +08:00
Oliver Jowett 6dc0741481 Drop wheezy support.
Upstream Debian LTS support for wheezy ended in 2018.
2020-08-06 13:44:07 +08:00
Oliver Jowett 84dd2dfe0e Disable limesdr/hackrf support on jessie, stretch, wheezy 2020-08-05 20:28:50 +08:00
Oliver Jowett ce521f715a Strip out the long-dead --debug option code. 2020-08-05 20:14:57 +08:00
Oliver Jowett ce5cf89e60 If --device-type is given without a type, list the available types. 2020-08-05 20:12:06 +08:00
Oliver Jowett 2fa793d0d7 Add a separate --version arg. Don't spit out full help on option syntax problems. 2020-08-05 20:11:40 +08:00
Oliver Jowett f1bd1a5829 Packaging updates for limesdr support 2020-08-05 20:04:25 +08:00
Oliver Jowett 653ad6127a Use a bounce buffer for rtlsdr on ARM to work around zero-copy problems.
On 5.x kernels with the USB mmap problems fixed, the distributed librtlsdr
will use a zero-copy mapping for USB buffers. Unfortunately, there is
something about the nature of the mapping on ARM (at least on Pis) that
makes most access to the data extremely slow. The uc8_nodc converter is
about 35x slower in this case compared to working on a heap-allocated buffer.

Luckily, a plain memcpy() of the buffer is still reasonably fast, so
we can use a bounce buffer and copy the data out of the slow mapping, then
pass the copy to the converter. This mitigates most of the problem,
at the expense of always needing that extra copy (which does somewhat
defeat the purpose of zero-copy!)

Unfortunately, librtlsdr provides no reliable way to control or
detect the use of zero-copy mappings, so we have to assume the problem
is always there (at least on ARM) and pay the cost of an unnecessary
copy when zerocopy is _not_ in use, too.
2020-08-05 19:50:38 +08:00
Oliver Jowett d5d04060de Support older limesuite versions e.g. what's available on Raspbian Buster.
Unfortunately limesuite doesn't seem to provide an API identifier, so
we can't detect whether LMS_PATH_AUTO is supported or not. Change the
fallback to LMS_PATH_LNAW, since that appears to work on both mini
and full-fat limesdrs.
2020-08-05 19:50:38 +08:00
Oliver Jowett 1761b8ddc1 Fix hackrf compilation when uint64_t is not a long
(e.g. on arm, it's a long long)
2020-08-05 19:50:38 +08:00
Oliver Jowett e857d042aa 'make clean' should clean object files in oneoff/ too 2020-08-05 19:50:38 +08:00
Oliver Jowett c1f526b76d Clean up the bladerf driver a bit 2020-08-05 19:50:38 +08:00
Oliver Jowett 74607b31ed Factor out FIFO handling; reimplement as a linked list, not a circular buffer.
Update all the SDR implementation to use it.

This was getting pretty ugly with code getting copy&pasted in all the SDR
implementations. Unify it all and give it a simpler API. Linked list works out
much simpler than the circular buffer. Also, simplify copying the overlap region
around by just using a separate buffer (it's only a few hundred bytes long, so
the double copy is not a big deal).
2020-08-05 19:50:38 +08:00
Oliver Jowett aa2929196d If DUMP1090_VERSION is unset, use "unknown" as the version (not an empty string) 2020-08-05 19:50:38 +08:00
Oliver Jowett 104575c602 Might as well compile with -O3 2020-08-05 19:50:38 +08:00
Oliver Jowett 89a83767f3 hackrf: missing \n 2020-08-05 19:50:38 +08:00
Oliver Jowett 8b21104d66 Factor out sdr thread CPU monitoring 2020-08-05 19:50:38 +08:00
Oliver Jowett f82b7b7a8c Set SDR thread name if pthread_setname_np() is available 2020-08-05 19:50:38 +08:00
Oliver Jowett 01587a114a Make convert_benchmark build with -Wmissing-declarations 2020-08-05 19:50:38 +08:00
Oliver Jowett e8b5be519c Make Modes.exit an atomic_int to make cross-thread use a little simpler. 2020-08-05 19:50:38 +08:00
Oliver Jowett 8734ec9992 Remove a WIN32 #ifdef 2020-08-05 19:50:38 +08:00
Oliver Jowett bf8d6db148 Better defaults for MODES_DUMP1090_{VARIANT,VERSION} 2020-08-05 19:50:38 +08:00
Oliver Jowett 84b1975e76 Fix benchmarks make target 2020-08-05 19:50:38 +08:00
Oliver Jowett d59e3bb136 Clean up Makefile SDR_OBJ a bit 2020-08-05 19:50:38 +08:00
eric1tran 5db1f1e9ba Fix misspelled variable name bug 2020-08-04 14:38:07 -05:00
makrsmark 64abbd02db
Adding G150 and GLEX icons (#32)
* adding Gulfstream 150 icon

* Adding Bombardier Global Express icon

Co-authored-by: eric1tran <eric1tran@gmail.com>
2020-08-03 11:40:29 -05:00
Oliver Jowett 84c2d67601 limesdr: fix missing trailing \n 2020-08-03 18:05:32 +08:00
Oliver Jowett 26e3c23e6a Merge PR #75 (LimeSDR support);
fix conflicts;
select limesdr rx antenna based on antenna metadata so it works on a mini, too.
2020-08-03 18:03:55 +08:00
Oliver Jowett 9520740a12 limesdr: try to select an appropriate antenna based on the limesuite antenna metadata. 2020-08-03 18:02:27 +08:00
Oliver Jowett b70898cd27 Placate -Wmissing-declarations 2020-08-03 15:17:29 +08:00
Oliver Jowett 66ba823493 Merge branch 'limesdr' of https://github.com/Gluttton/dump1090 into Gluttton-limesdr 2020-08-03 15:16:32 +08:00
Oliver Jowett 6a9700a58c If no explicit library settings are given, try to detect what SDRs to support based on what pkg-config knows about. 2020-08-03 14:57:31 +08:00
Oliver Jowett 238bb2bb5d Merge PR #57: Added support for HackRF One 2020-08-03 14:47:11 +08:00
Oliver Jowett 8b6239fab7 Don't call hackrf_exit if hackrf_init failed;
don't call hackrf_close if hackrf_open failed.
2020-08-03 14:45:35 +08:00
Oliver Jowett 699576f3de Add missing \n to hackrf error messages 2020-08-03 14:45:04 +08:00
Oliver Jowett 9b79daadaf Make handle_hackrf_samples static to placate -Wmissing-declarations 2020-08-03 14:40:32 +08:00
Oliver Jowett 5261b98c95 Merge branch 'master' of https://github.com/kr105/dump1090 into kr105-master 2020-08-03 14:32:08 +08:00
Oliver Jowett 49d95744f2
Merge pull request #74 from ianrenton/master
Use set-response-header instead of add-response-header
2020-08-02 22:48:09 -05:00
Oliver Jowett 8d56c0af9d Turn on -Wmissing-declarations following #67 cleaning up a few places that triggered it 2020-08-03 11:44:34 +08:00
Oliver Jowett c890bb6125
Merge pull request #67 from neheb/st
Make more functions static
2020-08-02 22:42:07 -05:00
Oliver Jowett 5b964f67b8
Merge pull request #66 from jwbernin/master
Add commented-out HTTPS configuration section
2020-08-02 22:38:32 -05:00
Oliver Jowett 92889d3497
Merge pull request #62 from flyingstar16/master
Load lighttpd alias module before using alias.url
2020-08-02 22:36:37 -05:00
Gluttton bb158d929c limesdr: add ability to set bandwidth
Add ability to set calibration bandwidth via input command line options.
By default the bandwidth is equal to 2.5 MHz.

Test: connect LimeSDR device, try to set different bandwidth and check
    logs:
    $ ./dump1090 --device-type limesdr --limesdr-bw 5000000
    $ ./dump1090 --device-type limesdr --limesdr-bw 500000

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:22 +03:00
Gluttton 95ae1a92be limesdr: add ability to set LPF bandwidth
Add ability to set LPF bandwidth via input command line options.
By default the bandwidth is equal to the default sample rate 2.4 MHz.

Test: connect LimeSDR device, try to set different bandwidth and check
    logs:
    $ ./dump1090 --device-type limesdr --limesdr-lpfbw 2500000
    $ ./dump1090 --device-type limesdr --limesdr-lpfbw 500000

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:22 +03:00
Gluttton c32ed2866e limesdr: add ability to set normalized gain
Add ability to set the combined normalized gain via command line
options. By default the gain is equal to 0.75.

Test: connect LimeSDR device, try to set different gain and check logs:
    $ ./dump1090 --device-type limesdr --limesdr-gain 0.01
    $ ./dump1090 --device-type limesdr --limesdr-gain 0.5
    $ ./dump1090 --device-type limesdr --limesdr-gain 0.99

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:22 +03:00
Gluttton da1aeeeea6 limesdr: add ability to set RF oversampling ratio
Add ability to set RF oversampling ratio via command line options. By
default the default value is used.

Test: none.

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:22 +03:00
Gluttton eb476d2e75 limesdr: add ability to select RX channel
Add ability to select an RX channel by number. By default channel 0 is
used.

Test: connect LimeSDR device and try to select the RX channel by number:
    OK: $ ./dump1090 --device-type limesdr --limesdr-channel 0
    OK: $ ./dump1090 --device-type limesdr --limesdr-channel 1
    NG: $ ./dump1090 --device-type limesdr --limesdr-channel 2
        $ limesdr: Invalid channel number.

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:22 +03:00
Gluttton 7267d8aff9 limesdr: add ability to select desired device
Add ability to select a desired LimeSDR device by serial number. It is
not necessary to pass a whole serial number, but its key part is enough.
The first device which serial contains the passed key is selected.

Test: connect LimeSDR device and try to select it by serial number,
    below an example for a device with serial 0009081C05C00000:
    OK: $ ./dump1090 --device-type limesdr --limesdr-serial 9
    OK: $ ./dump1090 --device-type limesdr --limesdr-serial 90
    OK: $ ./dump1090 --device-type limesdr --limesdr-serial 908
    NG: $ ./dump1090 --device-type limesdr --limesdr-serial 999
    It hasn't been tested with several devices!

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-31 00:18:12 +03:00
Gluttton f314e20342 limesdr: set verbosity level via input options
Add ability to set verbosity level for LimeSDR messages via command line
options. The range of available levels is from 0 to 4 and defined by the
constants from the `LimeSuite.h` file:
 - LMS_LOG_CRITICAL 0;
 - LMS_LOG_ERROR    1;
 - LMS_LOG_WARNING  2;
 - LMS_LOG_INFO     3;
 - LMS_LOG_DEBUG    4.
By default the verbosity level is 3 (INFO).

Test: launch the program with different verbosity level and ensure that
    number of messages is changed, for example:
    $ ./dump1090 --device-type limesdr --limesdr-verbosity 4
    $ ./dump1090 --device-type limesdr --limesdr-verbosity 3
    $ ./dump1090 --device-type limesdr

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-30 00:39:37 +03:00
Gluttton 53183c0b2a limesdr: basic implementation of LimeSDR support
The commit provides a basic implementation of support for LimeSDR USB
receivers based on LMS7002 chip. The solution has several limitations:
 - passing parameters for tune LimeSDR receiver via command-line
   options is not implemented;
 - only hardcoded configuration is used (channel 0 of lower band LNA,
   LMS_FMT_I16 format, gain, bandwidth and timeout);
 - only one device is supported and it is not possible to select a
   desired one in case if several devices are connected to the host.

Test: compare the output of the program for RTL and LimeSDR receivers.
Environment:
 - RTL2832SDR dongle;
 - LMS7002M based USB LimeSDR board;
 - 800MHz-2200MHz omnidirectional antenna with SMA connector.
Procedure:
 - connect RTL dongle to the host and start the program with the
   following parameters:
   $ ./dump1090 --device-type rtlsdr --interactive
 - wait until several planes will be detected;
 - stop the program, connect the LimeSDR board to the host and restart
   the program with the following parameters:
   $ ./dump1090 --device-type limesdr --interactive
 - ensure that the same planes are detected.
Acceptance criteria: the same planes are detected using both receivers
   and track information matches with information from the
   FlightRadar24 application.

Signed-off-by: Gluttton <gluttton@ukr.net>
2020-07-29 23:09:27 +03:00
Ian Renton c89e3b9e9e
Use set-response-header instead of add-response-header
When accessing Dump 1090 JSON from another web server, I found that the "Access-Control-Allow-Origin" parameter was set twice ("*, *") which Chrome objected to. By changing "add-response-header" to "set-response-header" we ensure that the correct header is sent, but never duplicated.
2020-07-26 09:27:02 +01:00
eric1tran f2f19d49fb
Update openlayers to v6.3.1 (#73)
* Update openlayers to v6.3.1 and get existing source working with new version

* Organize ol source files a bit

Co-authored-by: erictran <eric.tran@flightaware.com>
2020-07-21 11:32:39 -05:00
biggezy 0dae3e4b4a
Allow custom selection of columns in aircraft table (#72)
* Front-end/styling of window with checkbox options to customize plane table columns

* Toggle checkbox functionality with persistence

* Toggle correct columns for each checkbox

* Add several more column options and fix up logic to show/hide columns

* Functional select/deselect all checkboxes; Needs optimization

* Set overflow-x to scroll on aircraft table

* Select Columns button styling

* Refactor toggleAllColumns()

* Separate legend from table scrolling

* Move aircraft table styling into css file

* Spacing

Co-authored-by: erictran <eric.tran@flightaware.com>
2020-07-21 10:00:32 -05:00
Eric Tran 74ef2e92bd Fix some html syntax 2020-07-16 16:56:00 -05:00
Eric Tran bce7e35e0e Display registration number in aircraft table if ident is not present 2020-07-02 10:43:23 -05:00
Rosen Penev 0df937e9c6
fix -Wmissing-declaration warnings
This should result in a smaller size.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-29 16:42:21 -07:00
John Berninger ae12414eed Change SSL certificate and chain location example 2020-06-16 08:17:26 -04:00
John Berninger d3658b9fe6 Add mod_openssl module to avoid warning 2020-06-14 16:33:11 -04:00
John Berninger ba8f3e6af0 Add commented-out HTTPS configuration section
In recent versions of Firefox and (especially) Chrome, ".dev" domains are
force-redirected to a secure connection (HTTPS) instead of HTTP. Not
supporting an HTTPS connection makes for a bad user experience, so we want
to make enabling SSL support easy. Since we don't issue certificates, this
section is commented out by default, and it will require modification.

This is done primarily for PiAware, though it is applicable to just the
Dump1090 project.
2020-06-14 16:16:55 -04:00
Oliver Jowett 651d6a4e0d Build with -fno-common to match GCC 10 behaviour on older
compiler versions, so that linkage problems are more visible.
2020-06-06 22:02:43 +08:00
Oliver Jowett 0793c64ee8 Clean up linkage of struct Modes to actually make sense.
(how did this work before? But it's been unchanged since at least
2013..)

Maybe fixes #65
2020-06-06 21:52:04 +08:00
Eric Tran 79c9877232 Add more ADS-B Category Icon mappings 2020-06-05 14:39:59 +00:00
Oliver Jowett 8879bcac86 Change 2-bit correction option to "--fix-2bit"
--fix --fix was a poor choice for this, as some existing configs
happened to specify --fix twice but only expected 1-bit correction.
So move 2-bit correction to a separate option.

"--fix" or "--fix --fix" now gives 1-bit correction.
"--fix-2bit" or "--fix --fix-2bit" or "--fix-2bit --fix" gives 2-bit correction.

Version bump to 3.8.2~dev
2020-05-02 14:55:36 +08:00
Claudio Moretti 0ff1275bf9 Comment-out the alias module load: disabled by default
Standard lighttpd will refuse to start if modules are loaded more than
once. Turn the module addition into a comment, explain why it's disabled
by default and in which cases you should enable it.
2020-04-03 14:26:25 +02:00
Claudio Moretti f1507d8f2e Load lighttpd alias module before using alias.url
On some instances of lighttpd, like the one that comes with PiHole, the
alias module is not loaded by default. This makes the configuration of
PiAware's lighttpd not work (see e.g.
https://discourse.pi-hole.net/t/pi-hole-and-piaware-lighttpd/9611).

This way we ensure that the alias module is loaded even on non-default
lighttpd configurations.
2020-04-03 11:50:51 +02:00
Determinant 258e3f9d65 turn off stratux support by default 2020-03-30 12:34:11 -04:00
Determinant 8ba24e8c3b put the timestamp at last 2020-03-28 22:51:31 -04:00
Determinant eb1d42e47a ... 2020-03-28 15:27:22 -04:00
Determinant 2f9c3fe0e1 clean up 2020-03-28 15:25:31 -04:00
Determinant 52338202d1 ... 2020-03-28 15:25:31 -04:00
Determinant b6f007a104 WIP: support stratux protocol 2020-03-28 15:25:31 -04:00
Eric Tran d6b8065c3b Release 3.8.1 2020-03-19 14:21:17 +00:00
Eric Tran 4241a9f1a0 Update changelog for 3.8.1 2020-03-19 14:20:22 +00:00
Oliver Jowett aa8f3b3c27 Bump script cache bust version 2020-03-17 15:24:51 +08:00
Eric Tran 2efbf20177 Merge branch 'range_rings' into dev 2020-03-03 16:21:41 +00:00
Eric Tran a273f72246 Merge branch 'view_toggle_fix' into dev 2020-03-03 16:20:34 +00:00
Eric Tran bfc45dc81d Handle cases where location is not set 2020-03-02 20:48:45 +00:00
Eric Tran 888e7de16d Text formatting 2020-03-02 19:57:28 +00:00
Eric Tran f13b96dc6b Refactor and reset range rings properly 2020-03-02 19:19:57 +00:00
Eric Tran 8bb95e9956 Put range ring initialization work into a function and populate text fields with currently set values 2020-03-02 17:40:42 +00:00
Eric Tran 08a326eb7c JS code to handle custom range rings in SkyAware 2020-03-01 17:20:53 +00:00
Eric Tran c71c39b0d7 Customizable range rings UI 2020-02-28 20:54:22 +00:00
Eric Tran 263e03f7c2 Add last position age to aircraft detail pane that was removed 2020-02-20 22:27:12 +00:00
Eric Tran 9406fa7a2e Fix js error when setting ShowFlags=false 2020-02-20 21:55:16 +00:00
Eric Tran 070bc9f23c Don't initalize sorting if "Group By Data Type" is checked. Also de-select the box and save state if another sort method is chosen 2020-02-20 20:16:14 +00:00
Eric Tran e5a87e91b7 Fix issue with "Group By Data Type" and "All Aircraft Tails" toggle views were not persisting across browser refreshes 2020-02-20 18:51:10 +00:00
Eric Tran dfbe32559e Adjust width for PiAware SkyAware banner in css file 2020-01-30 16:57:11 +00:00
Eric Tran 439f615552 3.8.1~dev 2020-01-30 15:16:44 +00:00
Oliver Jowett c3541bcbea Release 3.8.0 2019-12-30 22:16:12 +08:00
Oliver Jowett 940c8e47ea Update changelog for 3.8.0 2019-12-16 11:05:07 -06:00
Oliver Jowett 81e6f680ee Update aircraft db to 20191216 2019-12-16 10:22:46 -06:00
Carlos Pizarro 1223f7f29a
[HackRF] Added missing build configs and changed some functions to go along with the rest of the project. 2019-12-14 21:40:43 -03:00
Oliver Jowett d471249f17 Track ADS-B version separately for direct ADS-B, TIS-B, ADS-R
(both because direct vs ground station might be different, and
to avoid characterizing ADS-R or TIS-B aircraft as being DO-260B
when they're not)
2019-12-12 09:21:26 -06:00
Oliver Jowett 886b0d3f81 Treat ADS-R as a separate source type (higher priority than TIS-B, lower priority than direct ADS-B) 2019-12-11 12:43:19 -06:00
Jade Michael Thornton 404ac5dced
Update style.css hide scroll bar when not needed (#26)
Update style.css hide scroll bar when not needed
2019-12-11 09:55:24 -06:00
Carlos Pizarro 0f0696c97b
Added support for HackRF One 2019-12-09 18:55:40 -03:00
Jade Michael Thornton 4a21198081
fix problems with info box (#51)
fix problems with info box
2019-12-09 13:14:05 -06:00
byronbest f45e657583
no need to ease when not visible 2019-12-09 09:55:09 -08:00
byronbest 497776c642
animate only if already visible 2019-12-09 09:32:03 -08:00
byronbest 0878bd2ddc
change more indents to tab 2019-12-05 17:13:17 -08:00
byronbest 1a0ba50c4a
fadeOut when marker leaves canvas
also move fadeIn to position at new marker before showing infoBox
2019-12-05 17:06:18 -08:00
Oliver Jowett 201cb2f466
Merge pull request #55 from wiedehopf/cpr_fix
CPR / Position update fix / improvement
2019-12-04 18:36:07 +08:00
Oliver Jowett 105ec2098c "unreliable_tracks" -> "unreliable" in stats json as suggested in #56 2019-12-03 14:15:54 +08:00
Oliver Jowett aa59af32aa
Merge pull request #56 from toofishes/patch-1
Fix invalid JSON after addition of unreliable_tracks
2019-12-03 14:07:29 +08:00
Dan McGee 21743b03b7
Fix invalid JSON after addition of unreliable_tracks
When `unreliable_tracks` was added to the JSON output, the trailing `}` after `single_message` should likely have been removed.

Side note: should this just be `unreliable` since it is nested inside `tracks`? `all` and `single_message` don't have the `tracks` suffix.
2019-12-02 20:49:33 -06:00
Oliver Jowett f7123c41e5 When trying to correct a DF11 that had bits set in the top 17 bits of the
residual, use the full 24-bit syndrome.

Previously this would mask off the low 7 bits, which isn't particularly
great - it doesn't really make sense in that it implies a somewhat
random IID value, and it would actually only correct 20 possible bit
errors out of the 51 possible errors, 16 of which were errors in
the top 16 bits of the CRC itself. It is also risky as it will accept
a larger number of possible garbage messages as the lower 7 bits may take
any value.

Instead, use the full syndrome, assuming that the damaged message
had IID=0 - which seems more likely than assuming a random IID, since
IID=0 is used for acquisition squitters and should be arriving regularly.

The reduced rate of corrections for DF11 messages shouldn't have
much of an impact as DF11s carry very little data themselves - they
are mainly used to acquire the aircraft address. Once one good message
for an aircraft turns up (which would require IID=0 anyway before we'd
accept it) it doesn't really matter if we discard more damaged messages,
as they're not contributing to anything useful in the aircraft state
beyond air/ground status, which is also carried in many other messages.
2019-12-02 21:27:18 +08:00
Oliver Jowett ae29613d85 Exit view1090 on connection loss in non-interactive mode 2019-12-02 19:52:43 +08:00
Oliver Jowett a224f6f783 Put a warning header up in view1090 interactive mode when there's no connection 2019-12-02 19:51:06 +08:00
Oliver Jowett fb110802d6 When view1090 reconnects, re-send our connection settings on the new connection 2019-12-02 19:50:31 +08:00
Oliver Jowett 59170cbacb Tweak --net-ro-size / --net-ro-interval defaults 2019-12-02 13:49:48 +08:00
Oliver Jowett 4ab1938f97 Update package defaults to pass --fix (1-bit crc correction) to match the piaware-support generated config on sdcard images 2019-12-02 13:47:29 +08:00
Oliver Jowett c853db67d0 Remove duplicated --net-bo-port 30005 in default config 2019-12-02 13:40:23 +08:00
Oliver Jowett f868e4c010 Bump TSV_VERSION for verbatim mode / track reliability changes 2019-12-02 13:01:43 +08:00
Oliver Jowett ea9f81c605 Remove first_message field as it's now unused. 2019-11-28 13:56:11 +08:00
Oliver Jowett 19327926f1 Cooked vs verbatim was reversed, fix it 2019-11-27 22:28:09 +08:00
Oliver Jowett b2e9153653 Add stats for unreliable tracks 2019-11-27 21:41:33 +08:00
Oliver Jowett a8737f7916 Remove --aggressive entirely, replaced by "--fix --fix" to enable 2-bit FEC.
nb: messages with a correctable 2-bit error are only forwarded to network
clients that have enabled verbatim mode (and they will be forwarded with
the 2-bit error still present, so the downstream client must apply its own
correction if desired)
2019-11-27 21:09:19 +08:00
Oliver Jowett 8ffa43b65c Add a v/V Beast-format setting to control verbatim mode.
Make --net-verbatim just control the default setting.

0x1A '1' 'v' disables verbatim mode (send "cooked" output);
0x1A '1' 'V' enables verbatim mode

Support clients with different settings by switching them between output
writers depending on what setting they want, so clients with different
settings can co-exist (unlike the Mode A/C setting)

In cooked mode, FEC corrections are applied to messages before they are send
and only trustworthy messages are forwarded; this is the default case for
downstream clients that don't want to apply their own rules and are happy with
the decisions that dump1090 makes.

In verbatim mode, all messages are forwarded, but no FEC corrections are applied;
the downstream client needs to make its own FEC / noise filtering decisions.

Usually the default for new connections is cooked mode. --net-verbatim changes the
default to be verbatim mode.
2019-11-27 21:04:27 +08:00
Oliver Jowett 54409b4836 Split beast output into two separate writers for verbatim vs. non-verbatim
in preparation for supporting both types of connection in parallel
2019-11-27 21:01:46 +08:00
Oliver Jowett dfc588335a Move output filtering down a level into the individual output functions. 2019-11-27 20:57:01 +08:00
Oliver Jowett 54f2c54d8f Include only reliable tracks in aircraft.json, faup1090 output 2019-11-27 20:51:23 +08:00
Oliver Jowett 9500a2f2f7 Show only reliable tracks in interactive mode 2019-11-27 20:51:23 +08:00
Oliver Jowett 429e34db21 Include ADS-B version in interactive mode display 2019-11-27 20:51:23 +08:00
Oliver Jowett ce89cd08d9 Groundwork to track "reliable" messages & aircraft.
A "reliable" message is a DF17 or DF11 with good CRC.
A "reliable" aircraft is one that's probably real - we decide it's reliable when
we've seen enough reliable messages, or just enough messages in total, that it's unlikely
to be noise.
2019-11-27 20:51:23 +08:00
Oliver Jowett dda442c121
Merge pull request #54 from flightaware/settings_checkboxes
Fix settings checkboxes on high dpi screens
2019-11-25 21:29:07 +08:00
Oliver Jowett 3c76eeb51c
Merge pull request #53 from neheb/b
treewide: Replace usleep with nanosleep
2019-11-25 21:28:09 +08:00
Oliver Jowett 620cb3a720 Regenerate TypeDesignatorIcons based on internal FA icon mappings 2019-11-18 20:15:05 +08:00
Oliver Jowett a11576710d Make the stretch build be a backport. Add a build rule for buster. 2019-11-07 10:54:24 +08:00
Oliver Jowett f1fef5b8fc Add buster to the Jenkins build 2019-11-07 10:41:40 +08:00
Oliver Jowett 36ae24838f 3.8.0~dev 2019-11-07 10:40:24 +08:00
Matthias Wirth f67a31823b use accept_data for setting position_valid
Check the return value from accept_data to determine if we want to
use the decoded position.
Avoid a position from local CPR with a synthetic MLAT message being used
when the position may still be valid and either odd or even CPR already
stale allowing the MLAT CPR to be used.
Set the position expiration correctly for global surface CPR, the
previous code could have an up to 50 second old CPR being used, which
would result in combine_validity setting an expiry time for the position
only 10 seconds in the future.
2019-11-01 07:31:39 +01:00
Matthias Wirth aa2b205481 Fix update_position being called when neither CPR changed
When we have ADS-B CPRs and get for example a MLAT synthetic CPR, don't
call updatePosition as this messes up the position state.
2019-10-18 21:02:12 +02:00
James Wilson af786e6e85
Fix settings checkboxes on high dpi screens 2019-10-04 20:46:17 -05:00
Rosen Penev ffff5d6646
treewide: Replace usleep with nanosleep
usleep was removed in POSIX 2008 and is optionally unavailable with
uClibc-ng.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-10-03 18:10:46 -07:00
Oliver Jowett 089684e20f Merge branch 'dev' into staging 2019-09-11 13:05:31 +08:00
Oliver Jowett 25b3a34fff Add a versioned cache bust to all the javascript URLs 2019-09-11 12:59:51 +08:00
Eric Tran ae4a89b707 Release 3.7.2 2019-09-09 14:29:26 +00:00
Oliver Jowett dabb6fc135 Trigger build after bladeRF build; turn off build durability; turn off concurrent builds 2019-09-05 15:32:04 +08:00
byronbest 0ba4ba3fd7
fixed up the merge problems 2019-09-04 09:43:13 -07:00
Oliver Jowett 0a0fb46b5d Pass branch name to validate-packages 2019-09-04 23:55:48 +08:00
Oliver Jowett 1d29f5e059 Reject outright a libbladerf that's too old 2019-09-04 22:46:38 +08:00
Oliver Jowett 18d47fd5ff Fix polyfill for really old libbladerf-dev which doesn't provide an API version define 2019-09-04 22:14:56 +08:00
Oliver Jowett 4edb2e8e35 Use new build infrastructure scripts 2019-09-04 21:53:53 +08:00
byronbest a1a7d42e90
fix problems with info box
error when removing plane, moving outside canvas, weird overlapping marker solution using extents
2019-09-03 10:34:00 -07:00
Oliver Jowett e2761fc21d
Merge pull request #48 from wiedehopf/track_history_fix
SkyView: Fix aircraft trail handling
2019-08-16 18:46:49 +08:00
Oliver Jowett 6a0df00e2d Update aircraft DB to 20190816.
In addition to the usual updated data, this update fixes a number
of ICAO type designator errors in the FlightAware static data
export (notably for the A330).

Fixes #17
2019-08-16 15:42:01 +08:00
Oliver Jowett d0094d5abd Fix registration stride mappings with a non-zero offset.
registrations.js would miscalculate the end of the address range
in these cases, causing the mapping to be skipped for addresses
that we could have handled.

This specifically affected German registrations beginning with
D-AP through D-AZ and D-BP through D-BZ
2019-08-16 15:19:44 +08:00
Oliver Jowett 35299c47ba Have filter-regs emit a special value "-COMPUTED-" for filtered data values,
rather than blanking them out entirely.

This lets csv-to-json.py handle the case where an earlier input file has (e.g.)
a registration value which does not match the computed value, and then a later
input file has a value that does match. In this case we want to override the
older value with the newer value, then notice that the registration can be
omitted when writing the database. Previously in this case the older (incorrect)
value would be used.
2019-08-16 15:16:55 +08:00
Oliver Jowett 0d2bd6ae34
Merge pull request #49 from wiedehopf/markers-fix
Fix some display errors
2019-08-13 19:38:32 +08:00
Eric Tran 1ecc925ed5 Remove wheezy from Jenkins build process 2019-08-01 13:57:53 +00:00
Eric Tran d9a78636a6 Version bump to 3.7.2~dev 2019-07-31 16:28:21 +00:00
Eric Tran 9cef820dfc Merge branch 'SkyAware' into dev 2019-07-31 16:23:20 +00:00
Matthias Wirth f1cb09d0e3 SkyView: Fix trail color for planes that are now on ground
When determining the color for a given altitude, don't check the current
altitude if it's ground but the altitude passed as an argument to the
function.
Without this fix, when clicking an aircraft on ground, its entire trail
is drawn in the color for ground.
2019-07-30 13:30:03 +02:00
Matthias Wirth 207ca0c401 SkyView: Unify stale check for loading the history
When loading the history, the check for stale aircraft tracks is done
differently.
This results in lots of dotted/stale track after opening the web page.
Improve this by using the same 5 second timeout stale criterion to
postions loaded from history. Add an additional check to better detect
stale tracks when loading history positions that are spaced 30 seconds
apart.
2019-07-30 13:24:11 +02:00
Matthias Wirth 76ab0a7ebe SkyView: Fix ground markers
Add width and height to the svg xml description of the markers/symbols
for ground vehicles.
Fixes thouse markers/symbols being invisble.
2019-07-30 13:03:21 +02:00
Eric Tran b01f42097d Add new SkyAware banners 2019-07-29 15:24:56 +00:00
Matthias Wirth 5cc04d4ca8 SkyView: Fix aircraft trail handling
Make aircraft trail handling more consistent and the code hopefully
easier to understand.
Fix position comparison (comparing array references does not work).

When initially loading the SkyView webpage, there are sometimes gaps in
the aircraft trails when the trail transitions from estimated/dotted to
known/solid track.

Fix elastic band style to handle estimated segments properly.
2019-07-27 17:46:23 +02:00
Eric Tran de6d671ba4 Change all occurences of Skyview to SkyAware in .js files 2019-07-16 19:11:19 +00:00
Eric Tran f4537bd49a Change all occurences of Skyview to SkyAware in code 2019-07-16 15:36:16 +00:00
Oliver Jowett ef125bd5f0 Bump TSV_VERSION for TAH sense fix. 2019-06-06 14:17:27 +08:00
Oliver Jowett e444d2eb5c Fix reversed sense of Track Angle / Heading bit in surface opstatus messages. 2019-06-06 14:15:14 +08:00
Oliver Jowett a0bd957274 Merge PR #46 2019-05-06 10:24:47 +08:00
Oliver Jowett fa65517ada standart -> standard 2019-05-06 10:23:28 +08:00
henry1952 64236c55d8
Update README-json.md
added nav_altitude_mcp, nav_altitude_fms
2019-05-05 19:32:40 +02:00
Eric Tran 40614778bc Release v3.7.1 2019-05-03 12:37:46 -05:00
Oliver Jowett 17f1054dff Partial merge of #44 2019-05-03 17:20:29 +08:00
Dalton Flanagan 7c57d8095b
Merge branch 'dev' into patch-1 2019-05-02 23:00:26 -07:00
Dalton Flanagan e30b3e87f5
Update README.md 2019-05-02 20:41:20 -07:00
Dalton Flanagan 68ca0dc800
Tweak README commands for easier copy & paste
Right now all of these commands are in plaintext in a single line. Splitting them in a code block makes it more readable and easier to copy and paste directly into a terminal.
2019-05-02 20:39:24 -07:00
Oliver Jowett 01b07ec50a Merge branch 'pr-39' into dev 2019-05-02 22:19:19 +08:00
Oliver Jowett 16f1d450ae Some corrections to json doc updates 2019-05-02 22:15:41 +08:00
Oliver Jowett 930e158208 Update aircraft DB to 20190502 2019-05-02 18:54:59 +08:00
Oliver Jowett 61f483c3e7 Bump TSV_VERSION to reflect extensive comm-b changes 2019-05-02 18:30:32 +08:00
Oliver Jowett 39aeb7a48c Remove comm-b "consistency" bonuses, look at inconsistent data only.
Rescale penalties so badly inconsistent messages will tend to get
the same penalty in all formats, so the ambiguity check kicks in.

With this final change the HEADING_SPEED and TRACK_TURN message rates
are almost identical, which is what we'd expect to see if the
interrogator is asking for both at about the same rate.

Before:

    567 AMBIGUOUS
   7445 GICB_CAPS
  19173 EMPTY_RESPONSE
  75252 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 212654 HEADING_SPEED
 223068 DATALINK_CAPS
 229807 TRACK_TURN
 269267 VERTICAL_INTENT
    466 "suspicious"

After:

   7445 GICB_CAPS
  17432 AMBIGUOUS
  19173 EMPTY_RESPONSE
  75252 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 212718 HEADING_SPEED
 212878 TRACK_TURN
 223068 DATALINK_CAPS
 269267 VERTICAL_INTENT
    328 "suspicious"
2019-05-02 18:19:27 +08:00
Oliver Jowett 5eb0bd10ea Bail out on unlikely comm-b data values in more places.
Before:

    575 AMBIGUOUS
   7090 GICB_CAPS
  19173 EMPTY_RESPONSE
  71686 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 212887 HEADING_SPEED
 223068 DATALINK_CAPS
 230008 TRACK_TURN
 272746 VERTICAL_INTENT

    861 "suspicious"

After:

    567 AMBIGUOUS
   7445 GICB_CAPS
  19173 EMPTY_RESPONSE
  75252 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 212654 HEADING_SPEED
 223068 DATALINK_CAPS
 229807 TRACK_TURN
 269267 VERTICAL_INTENT

    466 "suspicious"
2019-05-02 18:06:17 +08:00
Oliver Jowett f968fea390 Just bail out of comm-b decoding early on really bad data, don't bother with a big negative score.
No change to test results.
2019-05-02 18:03:40 +08:00
Oliver Jowett d5741bf8c8 Require more fields to be populated in BDS5,0/BDS6,0 before we'll accept them at all.
Before:

   7090 GICB_CAPS
  10667 AMBIGUOUS
  19173 EMPTY_RESPONSE
  62527 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 210286 HEADING_SPEED
 223068 DATALINK_CAPS
 232824 TRACK_TURN
 271598 VERTICAL_INTENT

   2517 "suspicious"

After:

    575 AMBIGUOUS
   7090 GICB_CAPS
  19173 EMPTY_RESPONSE
  71686 UNKNOWN
  76469 AIRCRAFT_IDENT
 127603 ACAS_RA
 212887 HEADING_SPEED
 223068 DATALINK_CAPS
 230008 TRACK_TURN
 272746 VERTICAL_INTENT

    861 "suspicious"
2019-05-02 17:58:03 +08:00
Oliver Jowett c9bea6a21c Store comm-b gs in gs.selected to help the decoder tests out.
Usually this is set in track.c, but the tests don't use that code path.

This somewhat increases the number of "suspicious" messages found.
2019-05-02 17:54:48 +08:00
Oliver Jowett 27f41c178f Allow comm-b aircraft-ident messages containing @, but don't actually use the callsign.
before:
  62905 UNKNOWN
  76091 AIRCRAFT_IDENT

after:
  62527 UNKNOWN
  76469 AIRCRAFT_IDENT
2019-05-02 17:51:46 +08:00
Oliver Jowett b8fb5e5fe5 If there is no single best-scoring comm-b format, mark the message as ambiguous.
This mostly affects TRACK_TURN messages on my test set. before:

 127603 ACAS_RA
  19173 EMPTY_RESPONSE
 210286 HEADING_SPEED
 223068 DATALINK_CAPS
 243445 TRACK_TURN
 271644 VERTICAL_INTENT
  62905 UNKNOWN
   7090 GICB_CAPS
  76091 AIRCRAFT_IDENT

  15973 "suspicious"

after:

  10667 AMBIGUOUS
 127603 ACAS_RA
  19173 EMPTY_RESPONSE
 210286 HEADING_SPEED
 223068 DATALINK_CAPS
 232824 TRACK_TURN
 271598 VERTICAL_INTENT
  62905 UNKNOWN
   7090 GICB_CAPS
  76091 AIRCRAFT_IDENT

   2258 "suspicious"
2019-05-02 17:44:37 +08:00
Oliver Jowett 0306c7edfd Update .gitignore for new binaries 2019-05-02 17:31:08 +08:00
Oliver Jowett 564f033087 Add some oneoff tools for comm-b decoding testing 2019-05-02 17:29:46 +08:00
Oliver Jowett d33b1160f2 Add COMMB_AMBIGUOUS for Comm-B messages we're not sure of (not yet used) 2019-05-02 17:29:04 +08:00
Oliver Jowett 1b5b0dfa03 Put ais_charset in its own file to make building commb tests a little easier 2019-05-02 17:24:26 +08:00
Oliver Jowett 74d7ead41b Move convert_benchmark into oneoff/ 2019-05-02 17:21:56 +08:00
Oliver Jowett d575cc0d00 Fix the markup that got lost when merging da41d820f6 2019-04-29 21:31:18 +08:00
Oliver Jowett b84fffc443
Merge pull request #43 from jprochazka/build-instructions
jessie build instructions - suggest a particular libbladerf tag
2019-04-29 21:29:45 +08:00
Joe Prochazka f573b843c3
Merge branch 'dev' into build-instructions 2019-04-29 09:27:49 -04:00
Joe Prochazka da41d820f6
Proper libbladerf1 build instructions. 2019-04-29 09:10:34 -04:00
Oliver Jowett e419719731 Minimal polyfill to support building against both bladeRF1 & bladeRF2 libraries 2019-04-28 15:16:58 +08:00
Oliver Jowett 19f26968c7 Explicit instructions for stretch 2019-04-28 15:08:01 +08:00
Oliver Jowett 34bfe10317 Rework use of pkg-config to work around librtlsdr packaging bugs in ubuntu disco 2019-04-17 11:58:59 +08:00
Oliver Jowett f13f8dfce8 Fix prepare-build with DEBEMAIL et al containing spaces 2019-04-17 11:46:03 +08:00
Eric Tran 4d683ac50c Version bump to 3.7.1~dev 2019-04-15 11:26:51 -05:00
henry1952 857c56ca7b
Update README-json.md 2019-04-13 09:41:21 +02:00
Oliver Jowett 0f23e514c6
Merge pull request #31 from mhamlet/patch-1
Fixing markup of code parts in README
2019-04-13 11:46:28 +08:00
Oliver Jowett a24718feca
Merge pull request #41 from henry1952/patch-3
Fix an error in the bit range used to decode CF in DF18 messages (harmless)
2019-04-13 11:38:48 +08:00
henry1952 37e49906d1
Update mode_s.c 2019-04-11 19:01:07 +02:00
Eric Tran d54c452683
Merge pull request #40 from wiedehopf/overflow_fix
Overflow fix
2019-04-09 08:52:11 -05:00
Matthias Wirth 82c5ff6724 Fix possible missing \n termination of TSV messages
If the \n termination of TSV messages is missing, faup1090 encounters
the following error:
Caught background error: list must have an even number of elements
    while executing
"array set row [split $line "\t"]"
    (object "::faup1090" method "::FaupConnection::data_available" body line 28)

This missing termination with \n can happen when p == end is true in the
overrun check. vsnprintf will always terminate the string with \0, so if
the vsnprintf is called to write the to the last position in the buffer
(end-1), it will write \0 instead to terminate the string as not to
overflow the buffer.
To catch that possibility the overrun check is changed to p < end as
then vsnprintf is assured to have had enough room to write the \0
termination to end-1.
2019-04-08 20:29:56 +02:00
Matthias Wirth b281ceee7b Increase maximum TSV packet size
Due to commit 45886edc40
faup1090: write _v on every line, bump TSV_VERSION
and maybe other changes the TSV packets are bigger and some users have
reported the following error:
piaware[9040]: faup1090(27427): fatsv: output too large (max 600, overran by 20)

Fix this error by increasing TSV_MAX_PACKET_SIZE to 800
2019-04-08 20:03:57 +02:00
henry1952 d6bafd64a2
Update README-json.md
'type' and 'tisb' need to be filled
2019-04-07 18:09:07 +02:00
Michael Norton f497d7481f
Add FreeBSD support
FreeBSD support, reworked from earlier pr by @neveragainde
2019-03-31 17:57:48 -06:00
Michael Norton a2480a2769
Note about building with bladerf on mac 2019-03-31 15:21:20 -06:00
Michael Norton 8a6261d7c2
Header typedef workaround for newer MacOS versions
Newish version of MacOS's time.h already `typedef`s `clockid_t` but doesn't seem to `#define` anything indicating such; as a workaround assume that `#ifdef CLOCK_MONOTONIC` on a Mac means that `clockid_t` has been `typedef`'d.
2019-03-31 15:15:59 -06:00
Michael Norton 91e9635563
Restore cross-platform compatibility
Re-implements platform-specific build of compatibility functions. Had been removed by bef563b8a3.
2019-03-31 15:01:06 -06:00
Eric Tran 883399cee3 Bump version for piaware lat/lon fix 2019-03-29 19:05:26 -05:00
Eric Tran 0f2215c2ce
Merge pull request #36 from wiedehopf/lat_fix
Fix getting LAT/LON from piaware .env file
2019-03-29 16:54:09 -05:00
Matthias Wirth 91f3c3ce67 Fix getting LAT/LON from piaware .env file 2019-03-29 20:55:47 +01:00
Oliver Jowett a654c60d65 Release v3.7.0 2019-03-22 15:58:13 +00:00
Oliver Jowett 18c0758a67 Changelog, version bump 2019-03-21 22:18:19 +00:00
Oliver Jowett 77c8f9aafa Minimal skyview changes for nav_alt changes 2019-03-19 18:48:13 +00:00
Oliver Jowett f46640a5c2 Track and report autopilot FMS/MCP separately; also report autopilot altitude source. 2019-03-19 18:44:09 +00:00
Oliver Jowett 56aa2f7d1e Clarify some comments in v1 TSS 2019-03-19 18:23:49 +00:00
Oliver Jowett 45886edc40 faup1090: write _v on every line, bump TSV_VERSION 2019-03-19 18:10:38 +00:00
Oliver Jowett 14c458db8c Add an ENABLED line to /etc/default/dump1090-fa on upgrade if missing 2019-03-12 11:39:05 +00:00
Oliver Jowett 9136766b9c Set SyslogIdentifier on dump1090-fa 2019-03-11 18:21:31 +00:00
Oliver Jowett 719e004c7a Use %t in the service file 2019-03-11 18:16:00 +00:00
Oliver Jowett d66a05b019 Use a helper to start dump1090-fa so we can read ENABLED from the defaults file, like beast-splitter does 2019-03-11 17:01:16 +00:00
Oliver Jowett 0946d5165d changelog 2019-03-07 18:44:26 +00:00
Oliver Jowett 9dfc3e7aa6 Arrange to return a non-zero exit code if the SDR thread unexpectedly halts 2019-03-07 18:35:47 +00:00
Oliver Jowett 47e43778a6 Just use fprintf. 2019-03-07 18:19:23 +00:00
Oliver Jowett 28e7ccca8e If rtlsdr_read_async returns early, the device is probably hosed, give up;
rely on the caller of dump1090 to restart.
2019-03-07 18:15:47 +00:00
Oliver Jowett 10cfc13c3a More build deps 2019-03-04 15:43:45 +00:00
Oliver Jowett bd50f5d689 Version bump to 3.7.0~dev 2019-03-04 15:36:32 +00:00
Oliver Jowett 324491b0e6 Add fakeroot to try to make travis happy 2019-03-04 15:31:24 +00:00
Oliver Jowett 6abcebd0e4 Skyview: finish up init properly if there's no history to load 2019-03-04 15:17:16 +00:00
Oliver Jowett f04a71640a Skyview: try true_heading / mag_heading for icon rotation if track is missing 2019-03-04 15:13:51 +00:00
Oliver Jowett 671aac5f50 Merge branch 'master' into dev 2019-03-04 15:08:31 +00:00
Oliver Jowett c05aea65a4 Don't use DF18 when updating the known-Mode-S-address set.
DF18 transponders don't necessarily do Mode S, so we shouldn't assume
that Mode S messages from that address are valid merely because we
heard a DF18. If it really is Mode S equipped, we should hear a
DF11 at some point.
2019-01-21 20:11:12 +00:00
Oliver Jowett 9c124b3f2b When generating aircraft.json, leave space for the final line.
Otherwise if there are only a few bytes free at the end of the loop
there's no space for the final line and it won't get appended.

Should fix mutability/dump1090#240
2018-12-31 11:17:28 +00:00
Hamlet 983829bff6
Fixing markup of code parts in README 2018-11-21 15:53:40 +04:00
Gareth Williams bd14c822e3
Removed extra ; 2018-10-03 01:12:32 +01:00
Gareth Williams 9063761dd1
Update style.css 2018-10-03 01:00:58 +01:00
Oliver Jowett c8501cb41c Compute ADS-B v0 NACp/SIL from position message type 2018-09-19 17:09:11 +01:00
Oliver Jowett 3c02e8419d Fix another Rc decoding error. Fix Rc comments. 2018-09-19 17:05:39 +01:00
Oliver Jowett b327848d75 Fix Rc comparison logic 2018-09-17 22:40:48 +01:00
Oliver Jowett cdba7566fd Fix skyview display of geometric altitude 2018-09-11 17:33:37 +01:00
Oliver Jowett 2a7a1e16f6 Prepare for 3.6.3 release 2018-09-11 14:52:42 +01:00
Oliver Jowett d0cfbdf3cf Build automation 2018-08-28 23:15:31 +01:00
Oliver Jowett 8829b65ab2
Merge pull request #23 from flightaware/ignore_altitude_onGround
Ignore altitude if an airborne position message indicates it's on ground
2018-08-28 20:28:05 +01:00
Eric Tran f4692a3784 Ignore altitude reporting when part of airborne position message with air/ground=ground 2018-08-28 17:08:14 +00:00
Oliver Jowett e2c8d361f8 Don't copy package-* when preparing source 2018-08-21 19:53:33 +01:00
Oliver Jowett 7d17d8e1ff Version bump to 3.6.3~dev 2018-08-17 18:00:39 +01:00
Oliver Jowett ed23dbd6db
Merge pull request #21 from drakeapps/master
Update skyview with extended mode S data fields
2018-08-17 17:59:37 +01:00
James Wilson e31bee1909 More spacing 2018-08-17 11:33:35 -05:00
James Wilson 8eeb29ec32 Fix typo. Clean up CSS and spacing 2018-08-17 11:31:12 -05:00
James Wilson 8985b5ab86 Version planeObject also 2018-08-17 10:28:42 -05:00
James Wilson bf05a94f3e Show n/a for not known registration 2018-08-15 16:54:43 -05:00
James Wilson 4fbb336fa3 Show n/a for aircraft type on info pane 2018-08-15 15:41:47 -05:00
James Wilson 43fedd9c6d Move registration on hover box. Default to n/a 2018-08-15 11:50:14 -05:00
James Wilson e0bb6e11e7 Add registration and source to hover box 2018-08-15 11:21:35 -05:00
James Wilson 7d61b2aaab Add Selected to nav alt/heading. Replace dragger with bar on top 2018-08-13 16:41:30 -05:00
James Wilson 7bb2cfe01f Move FlightAware link to the top 2018-08-10 10:34:40 -05:00
James Wilson 65f44d99bf Actually remove the squawks section 2018-08-08 16:42:14 -05:00
James Wilson 963cb1aefb Add back in photos link. Add more descriptions and remove squawks section 2018-08-08 16:41:34 -05:00
James Wilson 71f2c99e96 Fix air/ground status. Tooltip/infoblock changes 2018-08-08 11:37:26 -05:00
James Wilson 540e5f8e95 Just use ft/m for the Rc display 2018-08-03 18:39:13 -05:00
James Wilson 3ec6ec1a9d Center info icon. Show highlight hover with select box 2018-08-03 15:03:19 -05:00
James Wilson 974e962a55 C should be subscript for RC. 0 = unknown 2018-08-02 13:32:05 -05:00
James Wilson ea7a2c1c09 Update NAC displays. Add RC 2018-08-02 13:04:44 -05:00
James Wilson 12151ed8f5 Prevent full page scrolling 2018-08-01 10:38:50 -05:00
James Wilson 6af6ff7c2b Fix NAC/NIC/SIL labels and content. Fix airframes padding. Fix info icon url 2018-07-31 18:25:11 -05:00
Oliver Jowett 01a4477c92 Fix mangled msec part in port 30003 timestamps 2018-07-31 23:49:05 +01:00
James Wilson 0983766a6c Add close button and airframes.org link 2018-07-31 16:12:03 -05:00
James Wilson 3298eb77b4 Add accuracy fields 2018-07-31 12:17:27 -05:00
James Wilson 3e4012e958 SkyView extended mode-s changes
* Add extended Mode-S info to infoblock
* Move the infoblock to the sidebar
* Resizable infoblock
* Add hover tooltips for infoblock labels
2018-07-30 17:51:18 -05:00
Oliver Jowett 20a16d50bd Prepare for 3.6.2 release 2018-07-27 18:34:22 +01:00
Oliver Jowett 41fa394278 Merge branch 'direct-sampling' into dev 2018-07-24 17:49:16 +01:00
Oliver Jowett 6c055c8c23 Update aircraft db docs 2018-07-24 17:31:43 +01:00
Oliver Jowett 2b00c05465 Add --direct option for rtlsdr direct sampling 2018-07-23 20:37:01 +01:00
Oliver Jowett 1caabc5ad8 Update FlightAware registry data export; regenerate json db. 2018-07-20 21:14:23 +01:00
Oliver Jowett b82922e81c Strip out bad callsigns seen in ADS-B ident messages.
Same rules as apply to Comm-B - alphanumeric + space only.
2018-07-20 20:56:28 +01:00
Oliver Jowett d3448b0efb Update flags for Libya, Serbia, Montenegro 2018-07-20 20:49:11 +01:00
Oliver Jowett dfdee153ef Bump version to 3.6.2~dev 2018-07-20 20:34:33 +01:00
Oliver Jowett 655d311a37 Prepare for 3.6.1 release 2018-07-16 15:00:56 +01:00
Oliver Jowett fffd3c9913 Bump TSV_VERSION due to 7x00 handling change 2018-07-10 23:38:47 +01:00
Oliver Jowett 39b008472f Disable 7x00 -> emergency status translation.
This doesn't add information and it can actually obscure the true
source of the data (ADS-B emergency vs ADS-B squawk).
2018-07-06 19:54:58 +01:00
Oliver Jowett 6e7c32bde0 Give up on a single control file for jessie+stretch, just handle the dependency difference separately. 2018-06-29 12:54:33 -05:00
Oliver Jowett f81044cc01 Try to dance around the libbladerf version confusion between upstream & debian 2018-06-29 11:55:59 -05:00
Oliver Jowett 9101d5017d Generalize prepare-wheezy-tree for other distributions.
Add support for jessie backports
2018-06-21 17:13:57 -05:00
Oliver Jowett 60c762c843 Version bump to 3.6.1~dev.
Fix tracking of NICbaro.
2018-06-12 01:13:03 +01:00
Oliver Jowett 3340e6315c Fix changelog timestamp 2018-05-09 22:34:38 +01:00
Oliver Jowett fcbf32dc49 Prepare for 3.6.0 release 2018-05-09 17:34:20 +01:00
Oliver Jowett f4fa94f842 Merge branch 'more_mode_s' into dev 2018-05-09 16:20:58 +01:00
Oliver Jowett c9997a783f Also turn on extended data with #extended in the URL 2018-05-09 15:33:26 +01:00
Oliver Jowett c9e729a48a Hide extended data fields by default 2018-05-09 15:20:45 +01:00
Oliver Jowett 084acd2951 Remove chartbundle WAC, add helicopter chart.
(See https://github.com/mutability/dump1090/pull/212)
2018-05-09 15:16:05 +01:00
Oliver Jowett 9efd6b3470 Mapzen is shutting down, remove the mapzen support 2018-05-09 15:08:40 +01:00
Oliver Jowett 7749316540 Fix 10NM Rc value 2018-05-09 14:57:52 +01:00
Oliver Jowett d5eccc30a4 If we see a bad NIC supplementary bits combination, return RC_UNKNOWN 2018-05-09 14:57:29 +01:00
Oliver Jowett 0b9f7e4cef Fix up display of nav settings in skyview 2018-03-08 21:41:29 +00:00
Oliver Jowett d267d2257a Fix tisb/mlat json flag formatting 2018-03-08 21:15:41 +00:00
Oliver Jowett 213d769bf9 Tweaks to json output / webmap handling of new fields (untested) 2018-03-08 17:34:34 +00:00
Oliver Jowett d8f568e0ce Switch everything over to safe_snprintf
Rework the aircraft json overflow/resize case
Add more fields to the json, reorder to match header ordering
2018-03-07 20:10:50 +00:00
Oliver Jowett 0608e31965 Move some static functions earlier 2018-03-07 20:09:23 +00:00
Oliver Jowett a8fe04f856 Derive emergency status from squawk if not otherwise provided. 2018-02-23 19:02:33 +00:00
Oliver Jowett 5a9350a6a1 Derive SPI / Alert from the airborne position message surveillance status field 2018-02-23 19:02:02 +00:00
Oliver Jowett 94824fbb98 Avoid coredump on "untracked" aircraft (icao 000000)
Clean up the first-message-squelch logic a little.
2018-02-23 18:21:01 +00:00
Oliver Jowett 04b940d45b Switch RC_UNKNOWN to 0 to make life a little easier for faup1090/piaware 2018-02-23 18:10:49 +00:00
Oliver Jowett f323745ead Don't track icao 000000 as an aircraft
(but do still decode messages for it)
2018-02-23 18:10:26 +00:00
Oliver Jowett abfb88b124 Separate sil / sil_type to make compression a bit simpler 2018-02-22 07:45:32 +00:00
Oliver Jowett 5cdf9157db Add gva / sda to tracking state 2018-02-22 07:45:14 +00:00
Oliver Jowett f1036702ce Use the time we last saw a message for data validity checks / data age info,
rather than the time we eventually decide to emit it.
2018-02-22 07:42:22 +00:00
Oliver Jowett a256833e17 Increase the max tsv output size 2018-02-22 07:42:04 +00:00
Oliver Jowett 7059c0f64a adsbVer -> adsb_version 2018-02-20 00:26:16 +13:00
Oliver Jowett aa78020410 Emit changed emergency/priority status immediately 2018-02-20 00:25:49 +13:00
Oliver Jowett 286d8e7a10 tsvVersion -> tsv_version 2018-02-20 00:25:15 +13:00
Oliver Jowett d6c0612767 Remove doubled-up banner/header code 2018-02-20 00:24:39 +13:00
Oliver Jowett 1d5db2fd76 Fix baro/geometric rate flag sense in airborne velocity messages 2018-02-20 00:08:26 +13:00
Oliver Jowett 44e8913c2d Whitespace cleanups 2018-01-09 17:13:34 +00:00
Oliver Jowett daebc372a9 Write a version header on faup1090 startup 2018-01-09 17:12:33 +00:00
Oliver Jowett 0c3671429b Category 0 means not set. 2018-01-09 14:49:16 +00:00
Oliver Jowett 2ce2af1685 Tweak when we allow updates to air/ground status. 2018-01-09 14:47:08 +00:00
Oliver Jowett 571ea7ac41 Emit integrity info, when it changes. 2018-01-09 14:46:33 +00:00
Oliver Jowett 63d1b4b553 Consistency in *_enum_string naming 2018-01-09 14:45:18 +00:00
Oliver Jowett a947163dee Fix ADSBv0 ground movement decoding 2018-01-09 14:44:20 +00:00
Oliver Jowett ea1e9c336b Decode/emit emergency/priority status 2018-01-09 14:43:58 +00:00
Oliver Jowett 079061df3c SIL stuff 2017-12-07 13:36:07 -06:00
Oliver Jowett 161d2d8ded More WIP 2017-12-07 10:34:08 -06:00
Oliver Jowett 6986b3847f WIP on new faup1090 output, data aging, refactoring 2017-12-02 17:38:33 +00:00
Oliver Jowett 232a64e5fd Prepare for 3.5.3 release 2017-11-03 22:45:17 +00:00
Oliver Jowett d62f4c2ff5 Version bump to 3.5.3~dev
(Skipping 3.5.2 to align with piaware versioning)
2017-11-02 12:43:08 +00:00
Oliver Jowett a125155074
Merge pull request #19 from drakeapps/master
Update OpenLayers to current version
2017-11-01 17:48:25 +00:00
James Wilson a38acc3dff Update index.html to point to the correct OpenLayers files 2017-10-30 14:34:44 -05:00
James Wilson ee7d879130 Update OpenLayers to current version. This fixes slowness in certain browsers 2017-10-23 12:52:50 -05:00
Oliver Jowett 20c3c4b597 Tag & release 3.5.1 2017-07-31 13:43:45 +01:00
Oliver Jowett 3e207b5379 Changelog for 3.5.1 2017-07-31 13:41:55 +01:00
Oliver Jowett 220bbf5057 Fix L2P/L2T icon mappings, remove Dash 8 overrides 2017-07-31 13:16:19 +01:00
Oliver Jowett 51e3e1d677 Merge pull request #14 from daviessm/html_parallel_history_load
Parallelise the history JSON loads for faster initial load times.
2017-07-31 12:09:40 +01:00
Steven Davies 14bbf09230 Fix string concatenation to be addition 2017-07-29 19:18:56 +01:00
Steven Davies 74c9cb564c Parallelise the history JSON loads for faster initial load times.
As a by-product, for my test server using http/2 this halved the load time against the same code using http/1.1.
2017-07-29 17:52:24 +01:00
Oliver Jowett 567600889f Change color for on-the-ground aircraft to brown. 2017-07-28 17:37:55 +01:00
Oliver Jowett 43b0f5a75a Merge pull request #13 from kukabu/master
Code cleanup
2017-07-28 14:06:37 +01:00
Michael Tatarinov 18b455fbf0 Fix URL. 2017-07-28 15:51:30 +04:00
Michael Tatarinov 196ef89aca Cleanup after removed internal webserver code.
Fixes: 52464b97c1
2017-07-28 11:35:26 +04:00
Michael Tatarinov 417aee9dc5 Makefile: don't override the CC definition. 2017-07-28 11:30:09 +04:00
Oliver Jowett a3cdd47d80 ADSBv2 uses bit 15 of BDS1,0 2017-06-19 11:27:14 -05:00
Oliver Jowett 634d806686 Version bump to 3.6.0~dev 2017-06-19 11:12:23 -05:00
Oliver Jowett 4baae970ae Retain callsign even after it disappears from json. 2017-06-16 13:30:30 +01:00
Oliver Jowett c6d7f1ec6f Expire tracked true_heading, intent_modes 2017-06-16 11:42:41 +01:00
Oliver Jowett 2f53b57278 Fix typo in BDS6,0 scoring 2017-06-16 10:56:11 +01:00
Oliver Jowett f45a7d61a5 Include AP modes in info window. 2017-06-16 10:40:22 +01:00
Oliver Jowett 8a52108d77 Clean up js-side data capture, fix naming on ground track / speed. 2017-06-16 10:39:57 +01:00
Oliver Jowett 382554a250 Tweak tracking of AP modes, emit in json & faup1090 output 2017-06-16 10:39:01 +01:00
Oliver Jowett e3c8c91852 Emit adsb version in json & faup1090. Show it in skyview. 2017-06-15 23:42:05 +01:00
Oliver Jowett 17c8265ce8 Fix a few more things that were broken by the field renaming. 2017-06-15 22:41:32 +01:00
Oliver Jowett c7855c5ab6 Feed more data to skyview, basic display updates. 2017-06-15 22:36:23 +01:00
Oliver Jowett 1ec32903ba Rework heading/track to include HRD/TAH.
Clean up TIS-B flag output.
2017-06-15 21:07:53 +01:00
Oliver Jowett 05e9601903 Fix compilation. Emit some changes immediately in faup1090. 2017-06-15 18:30:12 +01:00
Oliver Jowett 27b0e9c40f Rename TARGET_* -> INTENT_ALT_*
Rearrange the intent tracking a bit.
2017-06-15 18:23:28 +01:00
Oliver Jowett 2142d2edf5 Whitespace changes only: cleaning up trailing whitespace at EOL 2017-06-15 18:17:07 +01:00
Oliver Jowett 98d64483d6 WIP: More Comm-B & ADS-B decoding. 2017-06-15 18:07:40 +01:00
Oliver Jowett 2e0aba4f1f Merge pull request #12 from drakeapps/master
Skyview Fixes
2017-05-09 19:41:06 +01:00
James Wilson 80eca0ff9a Always show correct source on data popup 2017-05-09 12:23:03 -05:00
James Wilson d225b9bc3f Fix event variable name 2017-04-25 18:28:57 -05:00
Oliver Jowett 0d7177fe9a Squawk/callsign might not be seen regularly from Mode S transponders
as it relies on SSR interrogation. Increase the FATSV validity
timeout so that any message we do see stays valid long enough to
get reported.
2017-04-21 22:25:41 +01:00
James Wilson bd96af9827 Check for other TIS-B types 2017-04-06 14:23:30 -05:00
James Wilson f1192e9414 Add fall back fonts for Helvetica Neue 2017-04-06 14:18:23 -05:00
Oliver Jowett fbb87b909f Update changelog for 3.5.0 2017-04-03 17:54:03 +01:00
Oliver Jowett 02b9e635b5 Update FlightAware aircraft data export. 2017-04-03 17:52:14 +01:00
Oliver Jowett c404e33198 Drop odd-count bytes and don't try to account for them later.
In cases where we do get an odd-length buffer (_very_ rare!)
it seems to be more about dropped USB data and not librtlsdr giving
us a partial callback; subsequent callbacks will still be aligned
with the I byte first despite the odd count.
2017-04-02 13:22:11 +01:00
Oliver Jowett 5ba613dd44 Only enable lighttpd config once, not on every upgrade. 2017-04-02 12:33:53 +01:00
Oliver Jowett 06cdc5071b Remove ShowClocks from config.js 2017-04-02 12:33:53 +01:00
Oliver Jowett 0aa1822262 Merge pull request #11 from drakeapps/master
Fix image sizing on retina displays
2017-03-29 23:39:16 +01:00
James Wilson 9486c14842 Fix image sizing on retina displays 2017-03-29 17:35:54 -05:00
Oliver Jowett 0c5472043e Don't explode on map pan after deselecting an aircraft that was being followed. 2017-03-22 22:29:42 +00:00
Oliver Jowett d790600a86 Merge pull request #7 from drakeapps/master
Update design and use SkyView branding
2017-03-22 22:26:20 +00:00
James Wilson 84383e2209 Prevent stroke when selecting all planes 2017-03-22 09:27:39 -05:00
Oliver Jowett 17c3a3fb6b Bump version to 3.5.0~dev 2017-03-22 11:31:45 +00:00
James Wilson f6dfe2616f Add stroke around selected aircrafts 2017-03-21 10:00:07 -05:00
drakeapps 87689cf6eb Add padding to right side of highlight box 2017-03-19 23:37:33 -05:00
drakeapps cfcb329a2f Add back in follow plane functionality 2017-03-19 23:05:44 -05:00
James Wilson 9621cadbd3 Merge branch 'master' of github.com:drakeapps/dump1090 2017-02-22 12:18:05 -06:00
James Wilson f23bdb21f6 Hide the altitude chart and checkbox if using custom colors since the chart is based on default colors 2017-02-22 12:17:18 -06:00
Oliver Jowett 3987cd59bc Merge pull request #9 from Mictronics/dev
Two bugs fixed
2017-02-22 17:00:06 +00:00
Mictronics 630136a1eb Fixed use after free bug. 2017-02-22 15:39:09 +01:00
Mictronics effca83150 Fixed bug that sets auto-gain to manual mode. 2017-02-22 15:38:35 +01:00
James Wilson 3a819a5aeb Merge branch 'dev' into master 2017-02-10 14:53:06 -06:00
James Wilson e0e09ed3a4 Add toggle to show/hide altitude chart 2017-02-10 14:41:48 -06:00
James Wilson fddb2298ee Clean up SVG rendering. Use the new flightfeeder key in status.json 2017-02-10 12:18:13 -06:00
Oliver Jowett 09f6bed7c0 Prepare for v3.4.0 release. 2017-02-09 17:43:48 +00:00
Oliver Jowett 0722edc2bc readme tweaks. 2017-02-09 13:40:08 +00:00
James Wilson d40e69ee42 Update the location it tries to put the infoblock if it's over the icon 2017-02-06 12:23:21 -06:00
James Wilson 2e6b4eb4b6 Update altitude chart dimensions 2017-02-03 16:33:39 -06:00
James Wilson b929821fe8 Update altitude legend with correct colors 2017-02-03 15:03:29 -06:00
James Wilson 484765a119 Only show layerSwitcher controls if there is more than 1 base layer present 2017-02-03 10:50:37 -06:00
Oliver Jowett 888c939a75 Include enabled compile-time build options in the help header. 2017-02-03 00:36:46 +00:00
Oliver Jowett aa5885b6df Add some notes about building libbladeRF to the README. 2017-02-03 00:36:46 +00:00
Oliver Jowett 7700cd90d3 Build/packaging work for the bladeRF 2017-02-03 00:36:46 +00:00
Oliver Jowett 0a6dc372ad bladeRF docs and custom bitstream. 2017-02-03 00:36:41 +00:00
Oliver Jowett 44129dca12 Add copyright headers to all the new files. 2017-02-03 00:36:41 +00:00
Oliver Jowett 2a8d6db055 Build with -DSC16Q11_TABLE_BITS=8 on armhf 2017-02-03 00:36:41 +00:00
Oliver Jowett 417cda7061 Make SC16Q11-nodc conversions table-based for speed.
Add a mechanism for converters to initialize tables on demand.
Move UC8 table setup to the new lazy-setup path.
Fix uc8 lookup table allocation size.
2017-02-03 00:36:33 +00:00
Oliver Jowett 8a41bcb730 Fix up end_cpu_timing (seems to break on Pi 1s otherwise) 2017-02-03 00:30:54 +00:00
Oliver Jowett bad821f5de Add a benchmarker for the sample converters. 2017-02-03 00:30:49 +00:00
Oliver Jowett cf9e3005e8 Add a bladeRF SDR type. 2017-02-03 00:30:42 +00:00
Oliver Jowett 234beb0bc4 Version bump to 3.4.0~dev 2017-02-03 00:29:45 +00:00
James Wilson 5d781785aa Add back in layer switcher. Update Select All/None button text 2017-02-02 18:21:07 -06:00
James Wilson bc2415bc5d Remove highlighting from map buttons 2017-02-02 17:31:00 -06:00
James Wilson cc92afd4f0 Increase size of the sidebar 2017-01-31 18:21:08 -06:00
James Wilson 0511d6fd3a Reset infoblock position on new plane selections. Update large ident styling 2017-01-31 11:07:39 -06:00
James Wilson 0e1e5df326 Align checkboxes with top line 2017-01-30 15:59:47 -06:00
James Wilson 06ab0502fe Chagne other and tisb row colors 2017-01-30 15:56:04 -06:00
James Wilson 773668f510 Change style of settings box and add close icon 2017-01-30 14:23:23 -06:00
James Wilson 973182c75e Remove retina altitude key styles 2017-01-30 12:39:19 -06:00
James Wilson 908d794238 Change altitude based on units. Increase width of altitude legend and use an SVG 2017-01-30 11:58:29 -06:00
James Wilson c34b1c38fb Make 'Show Map' button styling match header 2017-01-30 09:13:25 -06:00
James Wilson fbf8af2236 Don't show layerSwitcher on the map. We still want the functionality of it, but don't need the switcher panel currently 2017-01-27 16:01:20 -06:00
Oliver Jowett 75b221c0e3 Lots of refactoring to move the SDR-type-specific bits out of the
main code and make them optionally buildable.
2017-01-27 17:30:40 +00:00
Oliver Jowett bfc4b742af Move {start,end}_cpu_timing into util.c 2017-01-27 12:33:43 +00:00
Oliver Jowett b1149f344d Ditch a debug message. 2017-01-27 12:33:03 +00:00
Oliver Jowett b1a1771bb0 Speed up float converters a little, add a SC16Q11-nodc converter. 2017-01-27 12:31:34 +00:00
James Wilson ee23816428 Switch to FlightFeeder logo for FlightFeeders 2017-01-26 16:32:45 -06:00
James Wilson 9d3f3bdf84 Fix page height overflowing 2017-01-26 15:01:09 -06:00
James Wilson bee850061e Add functionality to ground vehicle and blocked MLAT filter
Add box shadow to header
2017-01-26 13:38:47 -06:00
James Wilson 6b699bffc3 Change the track for each altitude change to correctly color it based on altitude 2017-01-26 11:19:10 -06:00
James Wilson 6d4300848f Forgot a comma 2017-01-25 18:28:33 -06:00
James Wilson d332f477b8 Add ground vehicle icons 2017-01-25 18:19:09 -06:00
James Wilson d6898dbc49 Show altitude colors in plane track lines
Show altitude color key on map

Correctly handle retina images with CSS
2017-01-25 16:33:28 -06:00
Oliver Jowett cde047aac3 Merge pull request #6 from rparenton/see_photos_fix
Fix 'See Photos' link for hyphenated registrations
2017-01-25 19:14:05 +00:00
James Wilson a7be17a5d7 Chagne Track to Heading in infoblock also 2017-01-24 18:12:39 -06:00
James Wilson 4cbb1ab437 Round range rings labels. Add commas to altitudes. Change Track to Heading and add degree symbol. Remove the work Link from links 2017-01-24 18:10:06 -06:00
James Wilson e4a94aa574 Check for adsb_icao, not just adsb 2017-01-24 17:30:42 -06:00
James Wilson bbfdd45cc3 Merge https://github.com/flightaware/dump1090 2017-01-24 17:12:14 -06:00
James Wilson 8b9f984a54 Remove accidentally committed data folder 2017-01-24 17:09:39 -06:00
James Wilson 71b9b659d0 Use FlightAware aircraft icons 2017-01-24 16:54:06 -06:00
Robert 0afe1441de Fix 'See Photos' link for hyphenated registrations
\W would probably work for the regex, but I wanted to make it as narrow as possible.
2017-01-24 11:27:25 -06:00
James Wilson ac9249b293 Remove stroke from range ring labels 2017-01-24 09:34:42 -06:00
James Wilson e2fcc58bf2 Add labels to range rings 2017-01-23 16:27:03 -06:00
James Wilson 8228050ca4 Add settings pop up box 2017-01-23 14:02:45 -06:00
James Wilson 924bcaa044 Update more styling of the page. Add legend to table highlighting
Fix some indentation issues
2017-01-20 11:52:38 -06:00
James Wilson c2c43b9f6b Add date/time to header 2017-01-19 16:21:55 -06:00
James Wilson e5fcd4035f Redesign infoblock 2017-01-19 14:55:48 -06:00
James Wilson cf6fcdce6a Add retina images. Hide hover box on initial page load 2017-01-19 11:28:22 -06:00
James Wilson cc75121d37 Update map control icons 2017-01-18 18:14:27 -06:00
James Wilson 6c86d4f276 Add a smaller info pane that appears while hovering over planes 2017-01-18 16:14:53 -06:00
James Wilson b0dc4f8a4f Update header styling 2017-01-17 17:19:23 -06:00
Oliver Jowett a0c11c4156 Changelog. 2017-01-16 15:48:27 +00:00
Oliver Jowett 72e786af35 Tweak reported timestamps so that the relative timing of Mode S and
Mode A/C messages is the same as from a Beast/Radarcape.
2017-01-15 19:29:25 +00:00
Oliver Jowett 58e227897b Prepare for 3.3.0 release. 2017-01-15 13:36:15 +00:00
Oliver Jowett 9c935d95a5 Changelog. 2017-01-15 13:35:44 +00:00
Oliver Jowett 298525adc9 --max-range should not be overridable in faup1090. 2017-01-15 13:33:15 +00:00
Oliver Jowett 382b28767c Make package default max range match what the piaware sdcard image configures. 2017-01-15 12:50:10 +00:00
Oliver Jowett 814b4109f5 Changelog. 2017-01-12 13:54:59 +00:00
Oliver Jowett f2872d6c15 Update FlightAware static data export, regenerate the aircraft DB. 2017-01-12 13:52:22 +00:00
Oliver Jowett 1f0e75bce1 Changelog. 2017-01-06 14:51:21 +00:00
Oliver Jowett 52464b97c1 Remove internal webserver code entirely. 2016-12-29 18:35:35 +00:00
Oliver Jowett 64fd61cffc Don't process Beast mode A/C messages if mode A/C is disabled. 2016-12-29 17:57:53 +00:00
Oliver Jowett 6336611bc7 Turn on mode A/C if a Beast connection asks for it.
Add a --no-modeac-auto option to disable this.
2016-12-29 17:56:32 +00:00
Oliver Jowett cbdfd9dc5d Read Beast commands on Beast output clients, interpret the Mode A/C setting command. 2016-12-29 17:55:56 +00:00
Oliver Jowett 34aeb29347 Refactor the network input parser to make it easier to extend for new formats. 2016-12-29 17:54:53 +00:00
Oliver Jowett 0526388bdc Factor out sendBeastSettings(), use it in view1090. 2016-12-29 17:53:04 +00:00
Oliver Jowett 11b6cdba06 Rearrange fatsv location update message. 2016-12-27 19:15:56 +00:00
Oliver Jowett 4517055320 One less magic constant. 2016-12-27 19:14:20 +00:00
Oliver Jowett 4bb070be50 Add support for radarcape type 5 (receiver position) messages. 2016-12-27 19:07:10 +00:00
Oliver Jowett 5063efe064 Add #ifdef-ed code to display mode A/C signals graphically. 2016-11-12 17:13:36 +00:00
Oliver Jowett 32231cf142 Tweaks to A/C demodulator.
* use a global noise level rather than one computed from a few bits
 * work out level vs power confusion in some thresholds
 * fix the power calculation for working out the phase offset from
   the framing bits
 * require fewer quiet trailing bits
 * relax the bit-threshold tests
2016-11-12 17:10:29 +00:00
Oliver Jowett 5ef2612bb4 Version bump. 2016-11-12 14:09:18 +00:00
Oliver Jowett cc47718a2d Measure mean signal level in the converters.
Rearrange the meaning of the measured power level to be consistent
with the signal level.
2016-11-12 14:07:58 +00:00
Oliver Jowett 8182dc9a8f Preparing for 3.2.0 release. 2016-10-25 23:40:19 +01:00
Oliver Jowett 8f1663cb98 Prune the special handling for 000000 which is not needed. 2016-10-25 21:09:27 +01:00
Oliver Jowett 14748b1e8f Emit heading_magnetic correctly. 2016-10-25 21:05:03 +01:00
Oliver Jowett a4cf02a728 Changelog. 2016-10-24 22:02:23 +01:00
Oliver Jowett fe60f982cc Add ncurses to wheezy build dependencies. 2016-10-20 13:11:52 +01:00
Oliver Jowett c294ac1327 Allow skipping the history load by adding a #nohistory fragment to the URL
(e.g. for slow / high latency connections)
2016-10-14 22:09:35 +01:00
Oliver Jowett 8f3b7c8fde Realign the default infoblock position so it doesn't overlap the zoom control. 2016-10-14 22:04:44 +01:00
Oliver Jowett 78f88c6f8a Use the json type field to show finer-grained datasource info in the table mode. 2016-10-14 21:52:04 +01:00
Oliver Jowett 74ca8b838b Drop the maximum map marker size. 2016-10-14 21:44:21 +01:00
Oliver Jowett d3fad32d5e Merge remote-tracking branch 'upstream/master' into dev 2016-10-14 21:35:31 +01:00
Oliver Jowett 2b47fe5b68 Fix knots -> km/h conversion in interactive mode.
Fixes #153
2016-10-14 21:29:03 +01:00
Oliver Jowett 4cb17c194c More tweaking to A/C tracking. 2016-10-11 21:29:39 +01:00
Oliver Jowett f6b1b94c7d Use ncurses for interactive mode (reduces flicker on slow connections a lot!) 2016-10-11 20:37:28 +01:00
Oliver Jowett 25ea6d398b Overhaul mode A/C matching to be much cheaper.
The old matching process which tracked mode A values as pseudo-aircraft
got very, very expensive with a large number of mode A/C messages (and
with lots of single-bit errors, which seems common with a Beast doing
the reception)

Instead just count A/C messages directly into a 4096-entry array (which
is very fast) and periodically scan the mode S aircraft list to see if
we can match anything up (which is fixed overhead + cost proportional
to the number of mode S aircraft)
2016-10-11 18:00:11 +01:00
Oliver Jowett 60f1f3bcb6 Table-ize the Mode A to C conversions, add a Mode C to Mode A conversion function. 2016-10-11 17:57:25 +01:00
Oliver Jowett 10b5cde505 Fix interactive-mode row count so it doesn't scroll the header off the top of the terminal. 2016-10-11 17:55:23 +01:00
Oliver Jowett 85d3ecee62 Add source & address type for Mode A/C 2016-10-11 17:55:02 +01:00
Oliver Jowett eece2a54a0 Bump version to 3.2.0~dev 2016-10-11 14:16:07 +01:00
Oliver Jowett edb1eaeee2 Add the source file for the flightaware static data export. 2016-10-05 00:36:05 +01:00
Oliver Jowett 344415b91f Add a port-30003 regression diff script. 2016-10-02 13:27:13 +01:00
Oliver Jowett 52fe01c860 Track CPR encoding type directly rather than inferring it from airground.
(airground can change even while airborne if SPI/Alert status gets set)
2016-10-02 00:16:29 +01:00
Oliver Jowett 617a71e36b Fix a stray extra comma in port 30003 output if only GNSS altitude was available.
(cherry picked from commit 6f2e4fa891)
2016-10-01 15:22:42 +01:00
Oliver Jowett dda5411882 faup1090: Track Comm-B ACAS RA separately to ES ACAS RA as it's useful to see both reported.
Fix repeated reporting of ES ACAS RA reports.

(cherry picked from commit 14a003710e)
2016-10-01 15:22:32 +01:00
Oliver Jowett 7cd66c36d2 Increase the TSV packet size to accomodate all the extra data recently added.
(cherry picked from commit abc30ff656)
2016-10-01 15:22:14 +01:00
Oliver Jowett f6075212f4 faup1090: Reinstate TIS-B reporting as just the address type is
not sufficient if there is both TIS-B and Mode S for the same
aircraft.

(cherry picked from commit 32c8358bc1)
2016-10-01 15:21:53 +01:00
Oliver Jowett 5d681f4819 faup1090: Don't bother with the tisb field now that we have addrtype.
(cherry picked from commit df9648911e)
2016-10-01 15:20:50 +01:00
Oliver Jowett 812e4486a4 Merge remote-tracking branch 'upstream/master' into dev 2016-10-01 15:18:26 +01:00
Oliver Jowett 197fb2625a Tool to replay beast captures with the right inter-message timing. 2016-10-01 15:06:02 +01:00
Oliver Jowett 6f2e4fa891 Fix a stray extra comma in port 30003 output if only GNSS altitude was available. 2016-10-01 13:11:14 +01:00
Oliver Jowett 0c71b3db27 Fix up unsigned subtractions & use of abs.
Also fix heading difference which was just wrong, signed or not.

Should fix #150
2016-09-26 22:00:52 +01:00
Oliver Jowett 14a003710e faup1090: Track Comm-B ACAS RA separately to ES ACAS RA as it's useful to see both reported.
Fix repeated reporting of ES ACAS RA reports.
2016-09-24 16:09:38 +01:00
Oliver Jowett 2bcd0741c9 Prepare for 3.1.0 release. 2016-09-22 17:21:04 +01:00
Oliver Jowett c144507471 Actually serve data on 8080, not just a redirect.
(This is not ideal but plenty of people seem to be confused by the
redirect and how it interacts with NAT)
2016-09-22 16:49:45 +01:00
Oliver Jowett 802f1f9404 Add a redirect for map URLs with no trailing slash 2016-09-22 16:49:23 +01:00
Oliver Jowett cfb02c1a7c Try to avoid conflicting with other lighttpd config that
touches the stat cache settings.
2016-09-22 16:45:28 +01:00
Oliver Jowett abc30ff656 Increase the TSV packet size to accomodate all the extra data recently added. 2016-09-22 15:33:21 +01:00
Oliver Jowett c56245a954 Don't change marker color when using select-all. 2016-09-22 15:28:51 +01:00
Oliver Jowett 36e7ec4cd8 Fix the ident link. 2016-09-22 15:28:07 +01:00
Oliver Jowett b38061c3c4 Might as well use the mode-s-and-ident link everywhere. 2016-09-22 15:03:46 +01:00
Oliver Jowett d4e1300b1f Fix not displaying mode-S-only aircraft in the table. 2016-09-22 14:21:09 +01:00
Oliver Jowett 32c8358bc1 faup1090: Reinstate TIS-B reporting as just the address type is
not sufficient if there is both TIS-B and Mode S for the same
aircraft.
2016-09-22 13:53:40 +01:00
Oliver Jowett 2a2c1a805e Changelog updates. 2016-09-20 12:22:11 +01:00
Oliver Jowett 662c19568e Don't try to compute registrations on non-hex addresses (e.g. non-icao: ~123456) 2016-09-17 13:32:34 +01:00
Oliver Jowett 6e4eb4b35c Fix dh_auto_test on wheezy 2016-09-16 17:50:00 +01:00
Oliver Jowett 73a3b5113e More attempts at getting this working again on wheezy. 2016-09-16 17:43:21 +01:00
Oliver Jowett bef563b8a3 More hacking on the Makefile to get it working nicely on both jessie + wheezy. 2016-09-16 17:16:28 +01:00
Oliver Jowett b213ab9a50 Tweak wheezy build so it builds rtl-sdr itself rather than relying
on a librtlsdr-dev package that needs to be built separately.
2016-09-16 16:19:16 +01:00
Oliver Jowett daa3e00ade Restyle/realign the sidebar/layer controls some more. 2016-09-16 12:40:06 +01:00
Oliver Jowett 2a708ef848 Make the layerswitcher icon have a transparent background so it looks less out of place. 2016-09-16 11:43:48 +01:00
Oliver Jowett b2375468cb Stopgap fix for crowding in the top-right:
* move zoom control back to default position
 * shrink the sidebar expand/shrink buttons to half size
 * realign everything
2016-09-16 11:43:05 +01:00
Oliver Jowett df9648911e faup1090: Don't bother with the tisb field now that we have addrtype. 2016-09-16 11:19:26 +01:00
Oliver Jowett 4eb8e3d96a Set visible=false if we don't display a marker due to stale position;
this avoids markers briefly blinking back in on zoom.
2016-09-16 11:04:33 +01:00
Oliver Jowett bfa70415a3 Scale icons based on zoom level. 2016-09-16 11:03:54 +01:00
Oliver Jowett 4839372642 Oops, that was meant to be L4T. 2016-09-15 19:44:57 +01:00
Oliver Jowett 2843f85ed6 Add a L4P mapping. 2016-09-15 19:42:38 +01:00
Oliver Jowett 9bba9ce579 Remove dubious L1J, L2P mappings. 2016-09-15 19:42:17 +01:00
Oliver Jowett 227dce4af0 Scale tweaking. 2016-09-15 19:41:46 +01:00
Oliver Jowett fa17c472e7 Add a 747-400 icon, use it for 747 variants and L4J-H 2016-09-15 19:41:23 +01:00
Oliver Jowett efc47651e7 Update markers_test for the new marker selection stuff. 2016-09-15 15:31:15 +01:00
Oliver Jowett 2a4ee685a2 Merge remote-tracking branch 'upstream/master' into dev 2016-09-15 15:31:01 +01:00
Oliver Jowett 729d91c1ab Fix up address type categorization to match the spec. 2016-09-15 15:30:34 +01:00
Oliver Jowett 7c1fed98d2 faup1090: entirely blank (all spaces) idents are not interesting 2016-09-15 15:09:35 +01:00
Oliver Jowett 7e003097a0 faup1090: apply the same update rules to squawks/idents as to other data. 2016-09-15 15:09:22 +01:00
Oliver Jowett fb454c0a10 faup1090: accept squawks, idents as "useful" things. 2016-09-15 15:08:50 +01:00
Oliver Jowett 92136f3807 faup1090: only report airGround if we got a message confirming it since the last update. 2016-09-15 15:00:44 +01:00
Oliver Jowett 001f4956ea faup1090: report non-A-class categories. 2016-09-15 15:00:10 +01:00
Oliver Jowett 9653d365db faup1090: emit events from DF18 as well as DF17 2016-09-15 14:59:04 +01:00
Oliver Jowett 5b8a943cee Don't use a heavy outline on aircraft when select-all is used. 2016-09-15 12:38:11 +01:00
Oliver Jowett 5445ce143c Fix the final (elastic) line segment in trails so it works correctly
in both in the select-all case and the regular case.
2016-09-15 12:37:30 +01:00
Oliver Jowett 46f0c15471 Test page for markers. 2016-09-15 01:32:38 +01:00
Oliver Jowett d0f9b870cd Update static DB to include the FlightAware data export. 2016-09-15 00:09:57 +01:00
Oliver Jowett f8a2896e76 Merge remote-tracking branch 'csfa/map_enhancements' into dev 2016-09-14 22:53:50 +01:00
Carlos Salaverria 5fca9eed4b Change ICAO column font 2016-09-14 16:51:38 -05:00
Oliver Jowett 77ae0387ea Increase the DB block size. 2016-09-14 22:09:24 +01:00
Carlos Salaverria ad39d1b90c Use fixed width font for ICAO code column 2016-09-14 16:03:02 -05:00
Carlos Salaverria 4989111f67 Fix incorrect flagging of 000000 ICAO codes as mode A/C 2016-09-14 13:10:20 -05:00
Oliver Jowett 69031408f3 Add filtering of icao type descriptions / wtc based on descriptor. 2016-09-14 19:06:51 +01:00
Oliver Jowett d1790cd411 Prefer static DB type descriptions over the ICAO descriptor table lookup. 2016-09-14 18:25:21 +01:00
Oliver Jowett b59d0b6bcb Use the same mappings for categories A2/A3/A5 as for L2J-L/M/H 2016-09-14 18:18:39 +01:00
Oliver Jowett 256049f93a More scale tweaks. 2016-09-14 18:18:12 +01:00
Oliver Jowett 394b4d586e Make the selection outline bigger, make it in terms of pixels (unscaled), don't use the outline on the heading marker bit. 2016-09-14 18:02:00 +01:00
Oliver Jowett 809fcd9c59 Use the Dash-8 outline for L2T types. 2016-09-14 18:01:31 +01:00
Oliver Jowett 51b1851778 Scale up a couple of icons as they were way too small. 2016-09-14 18:01:12 +01:00
Oliver Jowett 7dee192157 Merge remote-tracking branch 'csfa/map_enhancements' into dev 2016-09-14 17:47:44 +01:00
Oliver Jowett d3d0912f03 Merge branch 'master' into dev 2016-09-14 17:38:02 +01:00
Oliver Jowett c0de65fe21 Bump the version to 3.1.0~dev 2016-09-14 17:36:44 +01:00
Oliver Jowett b260e1341e Merge remote-tracking branch 'upstream/master' into dev 2016-09-14 17:35:25 +01:00
Oliver Jowett 50a606d23f Make it clearer that ADDR_ADSB_ICAO includes Mode S too. 2016-09-14 17:19:49 +01:00
Oliver Jowett 4dacb291ab Fix tabs in faup1090 output. 2016-09-14 17:19:36 +01:00
Oliver Jowett 8441cf7d90 Emit non-icao addresses, address types from faup1090 2016-09-14 17:02:23 +01:00
Oliver Jowett 0ae2c5efc8 Emit addrtype in json output. 2016-09-14 17:01:07 +01:00
Oliver Jowett 8d8443f3dc Track the "best" addrtype we ever saw for an aircraft. 2016-09-14 16:54:00 +01:00
Oliver Jowett 2a4aa29f03 Record the address type details when decoding. 2016-09-14 16:37:07 +01:00
Oliver Jowett 10641303cb Add a couple more ME types. 2016-09-14 16:12:08 +01:00
Oliver Jowett 9e179d46bf Don't accept all-zeros messages (e.g. off the network - the demodulator
doesn't accept them already)
2016-09-14 16:11:31 +01:00
Oliver Jowett b827806ce8 Simplify ident decoding, add some sanity checks to the BDS2,0 case. 2016-09-14 16:02:20 +01:00
Carlos Salaverria f1428530c3 Fix ADS-B misspelling 2016-09-13 16:52:53 -05:00
Carlos Salaverria 20951fd23b Change default monospace font 2016-09-13 16:30:56 -05:00
Carlos Salaverria 6934c0dbcc Use text for Show Map button 2016-09-12 18:23:38 -05:00
Carlos Salaverria 2245aab7d1 Update FlightAware mode S link 2016-09-12 18:10:36 -05:00
Carlos Salaverria 08e0bd28f6 Allow aircraft info box to be positioned anywhere in browser window 2016-09-12 17:36:08 -05:00
Carlos Salaverria 976302e3ca Change ICAO column text to uppercase 2016-09-12 17:20:42 -05:00
Carlos Salaverria 647319d141 Fix alignment of altitude values 2016-09-12 17:08:22 -05:00
Carlos Salaverria e784b529a8 Fix JavaScript errors when receiver position is not set 2016-09-12 16:06:25 -05:00
Oliver Jowett ac2b977168 Merge remote-tracking branch 'upstream/master' into dev 2016-09-10 21:40:13 +01:00
Oliver Jowett 8e8b8588bf Merge branch 'master' into tracking-rewrite 2016-09-10 20:53:59 +01:00
Oliver Jowett d75cc94e40 Fix handling of nodejs module stuff when loaded in the browser. 2016-09-10 17:51:57 +01:00
Oliver Jowett 65a0f7f963 Compress vrs.csv since it's basically readonly. 2016-09-10 17:43:10 +01:00
Oliver Jowett 9b0d40fd4f CUTnnnn should be CU-Tnnnn 2016-09-10 17:39:42 +01:00
Oliver Jowett 2a3e4a0a0d Support reading multiple CSVs in csv-to-json.py 2016-09-10 17:26:55 +01:00
Oliver Jowett f45430e3b5 Warn about CSV mismatches in filter-regs.js 2016-09-10 17:26:36 +01:00
Oliver Jowett 2f12447fda Russian regs should be RA-nnnnn not RAnnnnn 2016-09-10 16:19:06 +01:00
Oliver Jowett aa916439e4 Prune the static DB with filter-regs.js 2016-09-10 16:07:38 +01:00
Oliver Jowett d1a33f4655 Add a script that filters redundant registrations from the json db 2016-09-10 15:54:59 +01:00
Carlos Salaverria 1ce66eb884 Change CSS styles to use FlightAware colors 2016-09-09 12:49:48 -05:00
Carlos Salaverria 83874f32ee Fix table scrolling 2016-09-09 12:07:34 -05:00
Oliver Jowett e5912c322f Add some mechanical hexid->registration conversions. 2016-09-09 17:16:17 +01:00
Carlos Salaverria 5b4ad4d8d9 Show mode A/C data in aircraft table 2016-09-07 14:20:42 -05:00
Carlos Salaverria 15c66a379a Fix incorrect test for Mode AC planeObject 2016-09-06 17:13:21 -05:00
Oliver Jowett 1958b23a93 Tweak the on-the-ground conditions a little. 2016-09-02 18:46:48 +01:00
Oliver Jowett 2636353e4a Fix aircraft-relative position validity check. 2016-09-02 18:41:59 +01:00
Carlos Salaverria 4ddb129b5e Fix map zoom button positioning in IE 2016-09-02 11:45:48 -05:00
Oliver Jowett f9419f13d5 Break up decodeExtendedSquiiter, it was getting pretty large. 2016-09-01 23:13:31 +01:00
Oliver Jowett a1fdc07db2 Restructure decoding to use a helper function to extract bit ranges
With forced inlining this is about as fast, and it is much less
errorprone than the twisty little maze of handcoded bitshifts that
it was before.

(notably, at least one error - in the ACAS RI field - has been fixed)
2016-09-01 22:45:49 +01:00
Carlos Salaverria cd8b48c282 Fix incorrect info box size calculation 2016-09-01 16:15:03 -05:00
Carlos Salaverria ffd661be84 Adjust table font 2016-09-01 15:50:21 -05:00
Carlos Salaverria 6199003fa1 Add transparent borders to increase size of marker clickable area 2016-09-01 14:55:02 -05:00
Oliver Jowett 303d3c3fef Make faup1090 emit iSource to say where the ident came from. 2016-09-01 19:11:33 +01:00
Carlos Salaverria e5902f2820 Automatically reposition info box if it overlaps plane marker 2016-08-31 17:59:24 -05:00
Carlos Salaverria bf1d1280ec Make aircraft info panel draggable 2016-08-31 15:45:29 -05:00
Carlos Salaverria 6934b8899a Merge branch 'master' into map_enhancements 2016-08-31 10:13:32 -05:00
Oliver Jowett ab8cc6be58 Release 3.0.5 (no changes) 2016-08-31 13:03:08 +01:00
Carlos Salaverria 7363152b93 Adjust button styles 2016-08-30 17:39:55 -05:00
Carlos Salaverria f2ea5a75bb Reposition map buttons 2016-08-30 17:20:29 -05:00
Carlos Salaverria a37c75bf83 Show additional data in selected aircraft info block 2016-08-30 16:38:41 -05:00
Carlos Salaverria 5de3bffcfa Deselect planes if map is clicked 2016-08-30 15:22:34 -05:00
Carlos Salaverria d5bd164169 Show selected plane information in separate panel 2016-08-30 15:07:54 -05:00
Carlos Salaverria 3588a47058 Adjust aircraft marker sizes 2016-08-30 13:35:58 -05:00
Carlos Salaverria 6accc36fd2 Move map zoom buttons to right side 2016-08-30 11:03:42 -05:00
Carlos Salaverria d5293cc0ed Add ability to map aircraft type descriptions to markers 2016-08-29 17:12:52 -05:00
Carlos Salaverria e13b09f1a4 Clean up aircraft type data inconsistencies 2016-08-29 14:45:05 -05:00
Oliver Jowett d7f7ffa70a Add support for markers that don't rotate but have a heading arrow.
Use it for balloons.
2016-08-29 13:45:37 -05:00
Oliver Jowett b04aec0ea1 Add A380 and B737-800 markers. 2016-08-29 13:45:22 -05:00
Oliver Jowett 413441e36d Add some more type->marker mappings. 2016-08-29 13:45:01 -05:00
Oliver Jowett 7541d89533 Fix the scaling comment. 2016-08-29 13:44:37 -05:00
Oliver Jowett 5e786e6cad Add more aircraft icons courtesy Peter Lowden.
Add support for selecting an icon based on aircraft type from the json DB.
2016-08-29 13:43:22 -05:00
Carlos Salaverria d17f027035 Add aircraft type information to planeObject 2016-08-29 10:07:03 -05:00
Oliver Jowett 08fba4e3b0 Add support for markers that don't rotate but have a heading arrow.
Use it for balloons.
2016-08-29 12:38:00 +01:00
Oliver Jowett 3e08de91ed WIP on decoding operational status & target state messages. 2016-08-29 11:11:04 +01:00
Oliver Jowett fa91b24ffa Use _DEFAULT_SOURCE to get ANSI-plus-defaults rather than
_BSD_SOURCE + _POSIX_SOURCE which newer glibc doesn't like.

Fixes #143
2016-08-28 23:48:17 +01:00
Oliver Jowett 08887642ea Rename the ACAS stuff a bit, emit ES target state. 2016-08-28 12:51:03 +01:00
Oliver Jowett 954034855a Make faup1090 emit some interesting messages when they occur. 2016-08-28 01:29:37 +01:00
Oliver Jowett 244ea9851d Add A380 and B737-800 markers. 2016-08-27 19:19:13 +01:00
Oliver Jowett 4d47ada055 Add some more type->marker mappings. 2016-08-27 19:18:57 +01:00
Oliver Jowett 4c79319145 Fix the scaling comment. 2016-08-27 16:43:17 +01:00
Oliver Jowett 158a8298fc Rearrange json DB stuff so it can work with CSV input. 2016-08-27 16:13:10 +01:00
Oliver Jowett ca57fb27f0 Add more aircraft icons courtesy Peter Lowden.
Add support for selecting an icon based on aircraft type from the json DB.
2016-08-27 15:49:04 +01:00
Oliver Jowett 54ca2c7fb2 WIP big rewrite of message decoding / aircraft tracking. 2016-08-27 14:34:14 +01:00
Oliver Jowett f152bf633e Build in C11 mode on Linux. 2016-08-27 13:15:41 +01:00
Carlos Salaverria 812de53ec1 Parse aircraft type codes 2016-08-26 16:22:14 -05:00
Oliver Jowett 36a5c16dd2 Initialize from static "zero" messages rather than using memset. 2016-08-26 21:39:39 +01:00
Oliver Jowett 8b8f8d7a40 Use INVALID_ALTITUDE in a few more places. 2016-08-26 21:38:06 +01:00
Carlos Salaverria 08ffda1aa8 Update aircraft db logic to include ICAO type information 2016-08-26 14:25:25 -05:00
Oliver Jowett 08c14484cd Use the haversine formula for small greatcircle distances, rather
than clamping to zero.
2016-08-26 11:36:29 +01:00
Oliver Jowett a910454c02 Comm-D ELM is actually DF 24..31, not just 24.
This DF is formatted with the first two bits as 1, and the next 3 bits
are part of the message rather than part of the DF code. So effectively
it spans 8 DF values if you are looking at the full 5 bits.
2016-08-26 11:35:11 +01:00
Oliver Jowett 308b928f8c If maxrange is 0, we cannot do receiver-relative CPR at all. 2016-08-26 11:31:32 +01:00
Oliver Jowett 43906f994b Limit aircraft-relative CPR to 50km. 2016-08-26 11:30:46 +01:00
Oliver Jowett 568e843b9f Add --max-range to view1090, use the same defaults as dump1090. 2016-08-26 11:29:42 +01:00
Oliver Jowett 8d998b2525 Rename --hae to --gnss since it's not always HAE.
(In the baro+GNSS modes, the reported GNSS can be either HAE or geoid-corrected MSL;
in the pure GNSS mode it is HAE only)
2016-08-26 11:27:46 +01:00
Carlos Salaverria 5290b58940 Update README 2016-08-25 16:49:36 -05:00
Carlos Salaverria 55bad33718 Added ICAO aircraft type information file 2016-08-25 16:46:37 -05:00
Carlos Salaverria 6b2c238a54 Add ability to filter planes by altitude 2016-08-24 15:28:13 -05:00
Carlos Salaverria e243a2bf1a Clean up and refactor unit conversion logic 2016-08-23 16:43:32 -05:00
Carlos Salaverria 4cc3fe4515 Fix improperly closed tag 2016-08-23 10:45:04 -05:00
Carlos Salaverria a2ca647062 Add link to FlightAware aircraft photos 2016-08-23 10:41:58 -05:00
Carlos Salaverria 70e86384f0 Add Airframes.org and FlightAware Mode-S links 2016-08-22 18:15:06 -05:00
Carlos Salaverria 96fe1e0ee5 Add ability to switch display units 2016-08-22 16:48:17 -05:00
Carlos Salaverria c99375d51c Add link to FlightAware flight tracking page 2016-08-19 18:45:39 -05:00
Carlos Salaverria 2215a98a08 Use icon for show map button 2016-08-19 17:57:20 -05:00
Carlos Salaverria 1c2bea38df Show additional columns when table is fully expanded 2016-08-19 17:37:43 -05:00
Carlos Salaverria 876e6874b4 Merge pull request #3 from drakeapps/map_enhancements
Add ability to select/deselect all planes
2016-08-19 17:01:14 -05:00
James Wilson 639b514e19 Merge branch 'master' into map_enhancements 2016-08-19 16:52:35 -05:00
James Wilson 31f99fac19 clearLines instead of updateLines 2016-08-19 15:52:48 -05:00
James Wilson b416f4bb7e Add the ability to select all/none of the aircraft 2016-08-19 14:43:20 -05:00
Carlos Salaverria 8bb5b42a02 Add ability to hide map and expand table to fill window 2016-08-19 10:58:48 -05:00
Carlos Salaverria fe2f837217 Add buttons to expand/collapse/resize data table 2016-08-18 15:48:57 -05:00
Oliver Jowett bc8ba5b73a Refresh the nexrad tiles every 5 mins. 2016-08-05 01:18:23 +01:00
Oliver Jowett 8766a58811 Add a NEXRAD layer suggested in #135 2016-08-04 21:19:31 +01:00
Oliver Jowett 50fd2ac2af Store the state of each overlay layer in localStorage. 2016-08-04 21:18:54 +01:00
Oliver Jowett 56397d6d78 Release 3.0.3 2016-08-01 12:24:09 +01:00
Oliver Jowett e136f30e32 Release 3.0.2 2016-07-27 17:13:28 +01:00
Oliver Jowett ad71d8b76c Merge remote-tracking branch 'mutability/master' into dev 2016-07-25 13:13:07 +01:00
Oliver Jowett 1887386149 Version bump. 2016-07-25 13:07:39 +01:00
Oliver Jowett ca3c4979f5 Add a note about quoting keys in config.js 2016-07-24 21:15:21 +01:00
Oliver Jowett 426e77a252 Don't choke when selecting positionless planes in the table. 2016-07-24 16:58:13 +01:00
Oliver Jowett 4305c99b01 Add Bing roadmap layer (if you have a key) 2016-07-24 16:25:14 +01:00
Oliver Jowett d3565b407e Generate geodesic circles for range rings.
Turns out that OL3's circles aren't geodesic circles so the
ranges are all off if you're anywhere but on the equator.
So generate our own LineStrings that approximate a circle.

Should fix #133
2016-07-24 16:13:04 +01:00
Oliver Jowett a06b13d42a Relax the A/C quiet threshold; this seems to pick up a lot more A/C messages. 2016-07-24 15:05:52 +01:00
Oliver Jowett b0452ab556 Preparing for 3.0.1 release. 2016-07-15 13:05:21 +01:00
Oliver Jowett ccb96af1b6 Update README. 2016-07-14 22:26:14 +01:00
Oliver Jowett 5d83077af2 Merge branch 'upstream' 2016-07-14 22:16:32 +01:00
Oliver Jowett 1e5a6fd854 Don't touch the GPS setting (I had it backwards anyway). 2016-07-13 10:56:54 +01:00
Oliver Jowett 474b564385 Try to configure whatever faup1090 connects to for the settings we want. 2016-07-13 10:02:15 +01:00
Oliver Jowett 4c6f0f156b Seems to work better on wheezy if we do a full lighttpd restart in postinst. 2016-07-12 18:58:42 +01:00
Oliver Jowett 7c3a300e60 Exclude .git from the wheezy package copy. 2016-07-11 19:54:07 +01:00
Oliver Jowett ebd066d883 wheezy packaging and initscript 2016-07-11 18:49:52 +01:00
Oliver Jowett 238b9d9e22 Plan C: Back to dynamic linking! We'll build a separate wheezy package. 2016-07-11 18:46:28 +01:00
Oliver Jowett 1272f6ba0a We also need the module blacklist. 2016-07-11 16:58:01 +01:00
Oliver Jowett 0aa404b928 Plan B: include a copy of librtlsdr's udev rules directly. 2016-07-11 13:24:21 +01:00
Oliver Jowett 29dd58c2f8 Add a Recommends: for librtlsdr0 to pick up the udev rules.
This was an implicitly added shared library dependency previously,
but static linking means that dependency is no longer present.
2016-07-11 12:46:11 +01:00
Oliver Jowett 0dde884ac7 Turn on static linking of librtlsdr
(an experiment to see if we can use the same packages on jessie and wheezy)
2016-07-11 11:38:43 +01:00
Oliver Jowett d6e42290de Add a transitional dump1090 package to help upgrades. 2016-07-11 11:03:51 +01:00
Oliver Jowett de94839339 Add a CORS header to data json files. 2016-07-10 15:26:44 +01:00
Oliver Jowett 1cb3e81989 Remove old cron stuff. 2016-07-10 15:26:33 +01:00
Oliver Jowett bf2b8efee6 Merge branch 'upstream' 2016-07-10 14:59:53 +01:00
Oliver Jowett b2aaa23984 Remove the last vestiges of the update-aircraft-db cronjob. 2016-07-10 12:22:32 +01:00
Oliver Jowett ad3d0e4d74 Upgrade the lighttpd dependency to Recommends 2016-07-10 12:13:49 +01:00
Oliver Jowett 9012b46ee1 Make the lighttpd enable/disable a bit more automatic. 2016-07-10 12:12:09 +01:00
Oliver Jowett ebfa6f63be Strip out the config options for the internal webserver. 2016-07-10 11:58:46 +01:00
Oliver Jowett e4ceea33da Disable the internal webserver at build time. 2016-07-10 11:56:31 +01:00
Oliver Jowett 9a10ef4886 Remove a stray "fi" in the initscript. Should fix #127. 2016-07-10 11:41:02 +01:00
Oliver Jowett d84bb22c24 Default to excluding the chartbundle layers. 2016-07-05 22:49:58 +01:00
Oliver Jowett a2d5d4abf7 Merge branch 'upstream' 2016-07-05 22:30:31 +01:00
Oliver Jowett 68ef9ce3be Add a note about the map API change. 2016-07-05 22:25:31 +01:00
Oliver Jowett b05510ccc5 Merge branch 'ol3'
This switches from Google's map API to OpenLayers, as using Google's API
now requires an API key which most users won't have (and it's not
practical to distribute a key with the project, as the free quota would
run out pretty fast)

This unfortunately means that we can't use Google's tiles, even with a key.
The map now defaults to OpenStreetMap; Bing and Mapzen tiles are also
available if keys are provided in config.js.
2016-07-05 22:21:09 +01:00
Oliver Jowett 6e1372708c Switch to OL 3.17.1; include a copy locally. 2016-07-05 22:07:26 +01:00
Oliver Jowett b93ada6196 Explain where to get map keys. 2016-07-05 21:54:24 +01:00
Oliver Jowett ae6a7acb67 Move aircraft icons above aircraft trails. 2016-07-03 14:54:36 +01:00
Oliver Jowett abab5f5440 Fix initial baselayer selection if no type was stored. 2016-07-03 14:54:14 +01:00
Oliver Jowett 2bbc117528 Base64-encode the SVG markers, seems to make Firefox happier. 2016-07-03 14:44:05 +01:00
Oliver Jowett 381ce5f280 Lots of layer cleanups.
Move layer config into a separate file.
Add a Mapzen vector tile layer.
Make the overlay layers toggleable.
2016-07-03 13:56:58 +01:00
Oliver Jowett 6676bc8172 Allow forEachRecursive to work on a collection/array. 2016-07-03 13:36:32 +01:00
Oliver Jowett 4862010d42 Don't gratuitously reverse the layer order in the switcher. 2016-07-03 13:35:54 +01:00
Oliver Jowett 6e8b7cff57 Expand the attributions control by default. 2016-07-02 21:53:07 +01:00
Oliver Jowett a357b9676d Keyless MapQuest access goes away shortly so remove that layer. 2016-07-02 21:13:10 +01:00
Oliver Jowett 2e68341106 Layer switching support, ChartBundle, Bing maps. 2016-07-02 21:12:31 +01:00
Oliver Jowett 49cb77ac8f Do stuff while animating/interacting. 2016-07-02 18:45:03 +01:00
Oliver Jowett 986c910a73 Turns out we don't need an interaction to catch feature clicks. 2016-07-02 18:11:05 +01:00
Oliver Jowett 54dc91adc5 Make table selection a little more robust. 2016-07-02 18:10:37 +01:00
Oliver Jowett 5cf512cf63 Clean out some debug, dead code. 2016-07-02 18:10:15 +01:00
Oliver Jowett b7fc52bcb3 Tweak the svg stroke width based on scale.
The stroke width is applied before scaling, but we actually want
the outline to have the same weight regardless of the scale chosen.
2016-07-02 17:14:58 +01:00
Oliver Jowett fc95719f2e Reinstate selecting aircraft by clicking on their icons. 2016-07-02 17:11:33 +01:00
Oliver Jowett 90f5a7d4e3 Round the computed colors a bit to reduce flickering.
(each color change requires regenerating the svg icon)
2016-07-02 17:11:08 +01:00
Oliver Jowett 18bd8b630d Draw plane icons. 2016-07-02 17:10:52 +01:00
Oliver Jowett 98564ab6d0 Add a scale. 2016-07-02 17:09:16 +01:00
Oliver Jowett 8639ab3837 More work on OL3. 2016-07-02 14:44:14 +01:00
Oliver Jowett 5acecbaf6f Starting to hack on OL3 support. 2016-07-02 12:55:38 +01:00
Oliver Jowett b1acfcf26a Switch to latest stable jquery/jqueryui. Include a local copy. 2016-07-02 11:00:27 +01:00
Oliver Jowett da437b3295 Set the socket buffer to the size of a HTTP response.
This gives us a better chance of the response fitting in a single
write() call (if it doesn't, it's going to get truncated, because
the internal webserver is really simple)
2016-07-02 10:51:23 +01:00
Oliver Jowett 22c90415be Check we got a full read when serving local files over HTTP. 2016-07-02 10:50:55 +01:00
Oliver Jowett dfe3d7af12 Merge pull request #126 from rxseger/osx
Test on latest Xcode for OS X 10.9, 10.10, and 10.11
2016-06-08 09:46:10 +01:00
rxseger 5d71b0dae7 Test on latest Xcode for OS X 10.9, 10.10, and 10.11 2016-06-07 18:16:48 -07:00
Oliver Jowett 999e55504a Merge pull request #125 from rxseger/unused
Remove unused functions in demod_2400
2016-06-07 10:17:28 +01:00
rxseger 75b69452ef Remove unused functions in demod_2400 2016-06-06 22:28:33 -07:00
Oliver Jowett d9408f96d3 Version bump. 2016-06-06 00:25:57 +01:00
Oliver Jowett bf042642c3 Increase the size of the heavy icon a little. 2016-06-05 21:43:28 +01:00
Oliver Jowett 42bf39e652 Merge pull request #117 from ertyu/ertyu-patch-1
Remove --net-fatsv-port from faup1090 help
2016-06-05 19:14:59 +01:00
Oliver Jowett 7c9320ad97 Update source comment for the new heavy marker 2016-06-05 19:13:55 +01:00
Oliver Jowett ee4dc696df Merge pull request #120 from danielmerritt/new-markers
New marker for heavy aircraft
2016-06-05 19:10:39 +01:00
Oliver Jowett 88cbd0acf7 Tweak the defaults a little. 2016-05-31 13:34:28 +01:00
Oliver Jowett e175e6593d piaware -> PiAware 2016-05-31 13:30:24 +01:00
Oliver Jowett 43e380912d Merge branch 'upstream' 2016-05-31 12:58:44 +01:00
Oliver Jowett 8b341f39e5 Add some paranoia so we notice if the receive thread wedges. 2016-05-31 12:42:22 +01:00
Oliver Jowett 56e80581f1 Remove --phase-enhance from the initscript. 2016-05-31 12:25:00 +01:00
Oliver Jowett 8f82e61f17 Remove the 2MHz demodulator.
Now that the 2.4MHz demodulator does 3A/C there's no real reason
to keep the old demodulator around.
2016-05-31 12:23:58 +01:00
Oliver Jowett b8dc3973d1 Always measure noise power, silently ignore --measure-noise if given. 2016-05-31 11:54:34 +01:00
Oliver Jowett acd38708cc Fix a couple of places that refer to "noise floor".
We measure the total power of everything we can't demodulate;
that's not really the noise floor.
2016-05-31 11:52:25 +01:00
Oliver Jowett d419b62a65 Always use phase enhancement; silently ignore --phase-enhance if given. 2016-05-31 11:47:57 +01:00
Oliver Jowett 93c135ea66 Remove a dead #define 2016-05-31 11:45:15 +01:00
danielmerritt c701b46559 Added a new marker for heavy aircraft 2016-05-16 22:47:56 +09:30
Oliver Jowett 824954aeca Call it 3.0~flightfeeder for consistency. 2016-04-12 18:20:45 +01:00
Oliver Jowett 62119c3306 Point mutability-repo package at the current version
as noted in #119
2016-04-12 14:57:09 +01:00
Oliver Jowett 2b292ca224 Version bump to 3.0 for FF image. 2016-04-11 17:55:30 +01:00
Oliver Jowett a628369228 Update PageName in config.js 2016-04-11 16:56:23 +01:00
Oliver Jowett 22fb17caf9 Call this "FlightAware dump1090" so it makes sense for both FF and Piaware images.
Update URL for the eventual home of this repo.
2016-04-11 12:12:11 +01:00
Oliver Jowett 50d67ff722 Merge branch 'upstream' 2016-04-11 12:11:05 +01:00
Oliver Jowett 7987598a72 Listen on port 8080 and redirect to port 80 for backwards compatibility. 2016-04-11 11:58:51 +01:00
ertyu bd1c82a445 Update faup1090.c
update help to match available operations
2016-04-07 15:27:10 -05:00
Oliver Jowett 162bf9d0b7 Merge pull request #116 from rgeissert/cppcheck-warnings
Cppcheck warnings fixes
2016-04-06 10:55:15 +01:00
Raphael Geissert 1269d73690 Fix another string format where %d is used but an unsigned int is passed 2016-04-05 21:05:36 +02:00
Raphael Geissert 859ba3b422 Fix some format strings that pass an unsigned int but use %d 2016-04-05 21:05:29 +02:00
Oliver Jowett e1278c36f7 Revert script.js indent changes from d00b07f361 2016-03-31 20:09:12 +01:00
Oliver Jowett d663094985 Merge branch 'htmlcleanup' of https://github.com/BowlesCR/dump1090 into BowlesCR-htmlcleanup 2016-03-31 19:55:51 +01:00
Oliver Jowett 5417fa6a53 Merge pull request #111 from WIZARDISHUNGRY/mutability-openbsd
Fix compilation on OpenBSD
2016-03-31 19:46:20 +01:00
Oliver Jowett e8919eada3 Merge pull request #112 from WIZARDISHUNGRY/mutability-homebrew
Use pkg-config for libusb, too, to work around pkg-config not generating the right link line for it.
2016-03-31 19:45:04 +01:00
Jon Williams e01b7b6740 Added libusb-1.0 to the list of libs handled by pkg-config 2016-03-31 14:04:09 -04:00
Jon Williams 83322511ad fixed a tiny change to an #ifndef comment 2016-03-31 13:46:17 -04:00
Jon Williams 953a5e0641 OpenBSD uses _CLOCKID_T_DEFINED_ instead of CLOCKID_T 2016-03-31 13:45:07 -04:00
Jon Williams e0c15ea7e8 changed MISSING_{NANOSLEEP,GETTIME} to use -D to fix compilation on OS X 2016-03-31 13:38:34 -04:00
Jon Williams 94706763e5 fix compilation on OpenBSD 2016-03-31 13:25:32 -04:00
Chris Bowles ebce0fdda6 Pedantic tweaks for HTML5 validation 2016-03-30 09:12:58 -04:00
Chris Bowles e509e76294 Avoid mixed-content warnings when served over HTTPS (in a protocol-relative way) 2016-03-30 09:12:22 -04:00
Chris Bowles d00b07f361 Indentation/Readability cleanup 2016-03-30 08:54:37 -04:00
Oliver Jowett dfc253bebf Merge pull request #110 from BowlesCR/planefinder
Add PlaneFinder link
2016-03-30 11:49:12 +01:00
Chris Bowles f53bca99e4 Add PlaneFinder link 2016-03-29 17:50:39 -04:00
Oliver Jowett 5f237db650 Version bump. 2016-03-24 22:56:00 +00:00
Oliver Jowett bdc1613512 Merge branch 'upstream' 2016-03-24 22:05:54 +00:00
Oliver Jowett 03c29a3721 Handle errors from rtlsdr_get_device_usb_strings.
Fixes #106.
2016-03-21 22:13:22 +00:00
Oliver Jowett 5781e6ab96 Be a bit more aggressive about rejecting noise in the space periods. 2016-03-20 20:49:30 +00:00
Oliver Jowett f6bdb61b13 Experimental 2.4MHz Mode A/C demodulator. 2016-03-20 19:49:37 +00:00
Oliver Jowett 0dc8336c14 Populate verbatim message for mode a/c. 2016-03-20 19:48:59 +00:00
Oliver Jowett 7a58e3cdc5 Move Mode C altitude calc into mode A/C message decoding.
If SPI is set, it cannot be mode C.
2016-03-20 19:47:27 +00:00
Oliver Jowett 85aa200947 Extra paranoia for --aggressive mode: only forward 2-bit-corrected messages
via paths that allow the recipient to see that they are 2-bit-corrected
i.e. raw or beast output in --net-verbatim mode only.
2016-03-03 12:39:01 +00:00
Oliver Jowett a434e1d076 Change of plan: don't statically link for jessie, but keep the option around for wheezy.
We'll have to do something to populate the udev rules on wheezy when we get to that.
2016-03-02 17:32:53 +00:00
Oliver Jowett bbb0e4553b Static link against librtlsdr. 2016-02-29 14:20:34 +00:00
Oliver Jowett c218bb9dfa Link to the new FA ModeS redirect URL 2016-02-27 16:14:12 +00:00
Oliver Jowett ccb9a6c034 Link to FA by hexid; clean up some dead code. 2016-02-27 15:52:02 +00:00
Oliver Jowett c6fff0ff32 Merge branch 'upstream' 2016-02-26 10:38:43 +00:00
Oliver Jowett 214bc0e587 Treat zero-or-missing signal levels as "no information" and don't include them in RSSI. 2016-02-24 11:55:01 +00:00
Oliver Jowett f7c9aed8b0 Merge pull request #103 from bjd/web-fixes
web view fixes
2016-02-18 22:19:30 +00:00
Bjorge Dijkstra a283ab2786 Fix check for valid distance in drawCircle() 2016-02-18 20:47:17 +01:00
Bjorge Dijkstra 3a98bf0d00 Remove invalid css property 'align' from timestamps div 2016-02-18 20:28:49 +01:00
Bjorge Dijkstra 1d723b0731 Remove sensor parameter from google maps api url, it is no longer required.
https://developers.google.com/maps/documentation/javascript/error-messages#sensor-not-required
2016-02-18 20:20:35 +01:00
Bjorge Dijkstra 99696cfac0 minor html syntax fixes for map view 2016-02-18 20:17:01 +01:00
Oliver Jowett b19c1f9dd2 Merge branch 'upstream' 2016-02-17 19:42:39 +00:00
Oliver Jowett ad3e4facb4 Merge pull request #102 from rgeissert/debian-copyright
Debian copyright
2016-02-16 21:20:38 +00:00
Raphael Geissert 008c1ee51b Add copyright information about markers.js 2016-02-16 21:35:13 +01:00
Raphael Geissert 7e317eac23 Add copyright information about clock_nanosleep 2016-02-16 21:05:14 +01:00
Raphael Geissert 2ea2181f30 Add copyright information about clock_gettime 2016-02-16 21:03:57 +01:00
Raphael Geissert 5b746d1414 Add copyright information about the flags-tiny pngs 2016-02-16 20:58:22 +01:00
Raphael Geissert 2dfd1320a6 Add copyright information about coolclock.js 2016-02-16 20:43:36 +01:00
Oliver Jowett b3769c241b Merge pull request #101 from rgeissert/aggressive-removal-fixup
Remove references to --aggressive from the maint scripts
2016-02-16 19:36:04 +00:00
Raphael Geissert 1c1b496a7a Remove duplicate crc.h copyright entry 2016-02-16 20:25:40 +01:00
Raphael Geissert ce38ddf127 Remove references to --aggressive from the maint scripts
Commit 577fe9b removed the debconf template for the option but the
maintainer scripts were still referencing it. This prevented the package
configuration from working.
2016-02-16 19:48:43 +01:00
Oliver Jowett eb16ac2028 Fix some termination issues. 2016-02-16 13:05:03 +00:00
Oliver Jowett a2eb71d49a IPv6 support (in theory).
Fixes #87.
2016-02-16 13:00:55 +00:00
Oliver Jowett 108b402918 Directly include the VRS-derived json db since the underlying DB
is not being updated any more.
2016-02-16 10:33:18 +00:00
Oliver Jowett 577fe9b52e Remove --aggressive from config options as the standard build will ignore it. 2016-02-16 10:12:22 +00:00
Oliver Jowett 8f58d0621c Revert the accidental change of default values for raw in/out ports.
This only affects standalone installs as the init.d script always
supplies all ports, overriding the compiled-in defaults.

Should fix #99
2016-02-08 21:39:21 +00:00
Oliver Jowett 20effc8cb8 Turn off --stats-every 2016-02-07 19:22:16 +00:00
Oliver Jowett e101351b6e Enforce max-range on mlat results (but still skip the speed check)
Fixes #97
2016-02-05 15:42:34 +00:00
Oliver Jowett 356cda2917 Flush stdout after writing message details so it works reasonably if there's also stderr output nearby. 2016-02-05 15:41:10 +00:00
Oliver Jowett 5de8a7b5f8 Merge branch 'upstream' 2016-01-26 11:28:08 +00:00
Oliver Jowett c510adbc94 $a is a literal sed command, avoid shell var expansion. 2016-01-25 15:23:59 +00:00
Oliver Jowett f9aa0398e5 Avoid creating a config file with all blank values if postinst configure fails. 2016-01-25 15:16:41 +00:00
Oliver Jowett 4711eaf741 Remove reference to net-fatsv-port in postinst.
Fixes #92.
2016-01-25 15:13:51 +00:00
Oliver Jowett cd86032be2 Fix return value sense of is_port_list
Probably fixes #91
2016-01-24 22:11:48 +00:00
Oliver Jowett 2a07897354 Be more selective about what is flagged as TIS-B. 2016-01-24 19:09:30 +00:00
Oliver Jowett 2b466535de Support multiple listening ports per listener type.
Beast input defaults to listening on both 30004 and 30104.
Drop the FATSV listener entirely (use faup1090 for that)
Ignore --net-beast.
2016-01-24 18:47:58 +00:00
Oliver Jowett 1a2926b311 Display ES data for DF=18, CF=2 when showing messages verbosely.
Always show an address for DF=18, using the NON_ICAO flag as needed.
2016-01-22 14:36:59 +00:00
Oliver Jowett cc04f315b4 Make the HAE/Baro offset field a bit clearer.
(given that I got confused by the old name after only a couple of weeks
away from that code..)
2016-01-22 14:36:17 +00:00
Oliver Jowett d02893fe3c Merge branch 'upstream' 2016-01-21 21:48:15 +00:00
Oliver Jowett c4e162287d Oops, sprintf -> snprintf 2016-01-21 20:22:18 +00:00
Oliver Jowett d9eec668cf Track what data we got via TIS-B, report it as such. 2016-01-21 19:42:37 +00:00
Oliver Jowett 1170ed9620 Set faup1090 default max range to 360NM.
This effectively disables receiver-relative CPR.
2016-01-21 19:01:11 +00:00
Oliver Jowett 5632a2ccdb Try to get travis working again. 2016-01-21 18:35:41 +00:00
Oliver Jowett ecbdbf23d6 Never forward mlat via SBS or raw output; it is no longer identifiable
as mlat when forwarded on those paths.
2016-01-21 17:48:06 +00:00
Oliver Jowett 5c3692a513 Require an explicit #define at build time to enable --aggressive. 2016-01-21 17:45:27 +00:00
Oliver Jowett b433a521bf Start trimming dump1090-mutability down for use in piaware. 2016-01-13 00:00:08 +00:00
Oliver Jowett 9479a5c9be If --hae is passed, report altitudes as HAE where available, with a H suffix.
This affects interactive mode and SBS output.
2016-01-01 15:15:28 +00:00
Oliver Jowett c99e4d9aed Factor out metric conversions, always report FL as feet-based in rtl1090 mode. 2016-01-01 15:14:34 +00:00
Oliver Jowett efd6b94310 Track HAE altitude separately to baro altitude where possible. 2016-01-01 13:42:30 +00:00
Oliver Jowett c4a2a5c9fb Fix the upintheair URL. 2015-12-23 10:10:05 +00:00
Oliver Jowett 75ddd87408 Basic support for terrain-limit rings based on data from heywhatsthat.com 2015-12-21 17:43:26 +00:00
Oliver Jowett 779c66e2e9 Reindenting. 2015-12-21 17:40:39 +00:00
Oliver Jowett 457761f060 Don't spam stats reports if the system clock jumps. 2015-12-19 18:28:12 +00:00
Oliver Jowett 497f88fe1c Don't match faup1090 tags when generating a version string from git tags. 2015-10-27 13:57:29 +00:00
Oliver Jowett f84e9a8de1 Fix the missing comma in the monochrome display example. 2015-10-26 23:09:26 +00:00
Oliver Jowett 91fce10f30 Remember map type selection in local storage.
Fixes #26.
2015-10-26 23:03:34 +00:00
Oliver Jowett ecc45517d6 Merge pull request #78 from dschaper/nginx
Add nginx config file for webmap
2015-10-26 13:19:51 +00:00
Oliver Jowett f8a3c46139 Add generic map type config for maps that can be handled by simple URL pattern substitution. 2015-10-26 12:59:38 +00:00
Oliver Jowett 482d3a1d38 Turn on scale (and zoom for good measure, though it's on by default) 2015-10-26 12:58:49 +00:00
Oliver Jowett 416c8591b7 Tweak the display of mlat aircraft icons (not convinced these are the best settings) 2015-10-26 12:30:21 +00:00
Dan Schaper 72e511594d Add nginx configs to packaging. 2015-10-25 10:23:51 -07:00
Dan Schaper a6cb388eef Add nginx config file 2015-10-25 09:20:22 -07:00
Oliver Jowett c55c71b57c Fix off-by-one error that would ignore maxRange if it was exactly 360NM. 2015-09-30 23:59:01 +01:00
Oliver Jowett 3b4c872ea6 Merge pull request #71 from maxried/master
--html-dir option
2015-09-14 20:34:32 +01:00
maxried 3d4455948f Update dump1090.c 2015-09-14 21:05:27 +02:00
maxried f8c6513294 Update dump1090.c 2015-09-14 20:48:17 +02:00
maxried f66420b275 Update dump1090.c 2015-09-14 20:47:30 +02:00
maxried 217e6f9216 Update dump1090.h 2015-09-14 20:44:52 +02:00
maxried 541f12fb21 Update dump1090.h 2015-09-14 20:11:00 +02:00
maxried 90adaf22f7 Update net_io.c 2015-09-14 20:03:19 +02:00
maxried 267e5d6909 Update net_io.c 2015-09-14 19:59:50 +02:00
maxried 37677f1557 --html-dir 2015-09-14 19:59:27 +02:00
maxried 392054a27b Add --html-dir option 2015-09-14 19:58:59 +02:00
Oliver Jowett 909f1ad1e5 Allow D2 in altitude values (>62k ft) 2015-09-10 14:22:13 +01:00
Oliver Jowett b51cafb91b Merge branch 'dstipp-master' 2015-09-07 13:04:51 +01:00
Oliver Jowett 1c80d1b784 OS X compatibility cleanups.
Reattach the licenses for the compat stuff to the source.
Only build/link the compat stuff when it's needed.
Rename compat/util.h so it's not confused with util.h.
Move all the platform specific defines inside compat/compat.h.
2015-09-07 12:58:49 +01:00
David Stipp ae126d1009 Add back Darwin/Mach/Apple portability
Quite a few of the changes against the MalcolmRobb/dump1090 fork are
incompatible with OSX.  This patch adds back that cross platform support
back.
2015-09-05 14:42:11 -04:00
Oliver Jowett ef34c4ce0f Put the CI status in the README 2015-09-03 10:36:34 +01:00
Oliver Jowett 46f3b722c9 Make it noninteractive. 2015-09-03 10:30:11 +01:00
Oliver Jowett 221f8bbb92 Try using the gqrx repo for librtlsdr-dev packages for 12.04. 2015-09-03 10:27:25 +01:00
Oliver Jowett 937e0ae3ca Trying out travis-ci 2015-09-03 10:14:52 +01:00
Oliver Jowett 4f24e008ba Merge branch 'Dynomity-flags' 2015-09-01 17:28:32 +01:00
Oliver Jowett 976dc44d11 Regenerate the ICAO ranges table based on data extracted from Annex 10. 2015-09-01 14:21:25 +01:00
Oliver Jowett b5960fd44a Cleanups, reformatting, a few bugfixes, add sort-by-country. 2015-09-01 12:19:23 +01:00
Oliver Jowett 7bebcc558f Merge branch 'flags' of https://github.com/Dynomity/dump1090 into Dynomity-flags 2015-09-01 11:06:42 +01:00
Oliver Jowett 05c8bc5d9f Merge pull request #45 from saiarcot895/add-curl-recommends
Add curl as recommends.
2015-08-31 22:59:52 +01:00
Dynomity 84ad8a2788 removed old commented line 2015-08-30 11:34:37 -06:00
Dino M 0858fa2af4 fixed colspan issue for position 2015-08-30 10:25:43 -06:00
Dynomity 9e00c2d0d3 Merge remote-tracking branch 'origin/flags' into flags
Conflicts:
	public_html/script.js
2015-08-30 10:19:53 -06:00
Dynomity 402e40fc36 fixed table display column problem
This is the final version for this project. (I hope!)
2015-08-30 10:16:40 -06:00
Dynomity b5d49b451b just cleaning up the formatting 2015-08-26 10:07:50 -06:00
Dynomity 8a1c08cafb Moved loading of flags.js above script.js 2015-08-26 10:00:19 -06:00
Dynomity 95f90fe799 file rename 2015-08-25 19:21:58 -06:00
Dynomity de426ba823 removed flag id 2015-08-24 20:35:00 -06:00
Dynomity c95e5775ff minor cosmetic tweaks around flags 2015-08-24 12:44:59 -06:00
Dynomity 899e072cf1 Added back the flag in the selected section 2015-08-24 12:39:37 -06:00
Dynomity 00f3f3723e removed Country column 2015-08-22 10:13:02 -06:00
Dynomity 9e94a6dc1a fixed North/South Korea elements 2015-08-21 18:44:27 -06:00
Dynomity baddeb9034 cleaning up code and plane table 2015-08-21 18:38:38 -06:00
Dynomity 1babb5b55c Added span for flag icon in selected 2015-08-19 22:00:57 -06:00
Dynomity 1a5e6e2187 searches in hex now.
The search now looks at the hex object array in flags.js. Also moved
the search in the planeObject section. See got to to figure out whether
I should add a new property for the image.
2015-08-18 22:37:34 -06:00
Dynomity 687720386f Removed decimal ICAO codes. Only hex objects 2015-08-18 22:31:13 -06:00
Dynomity 725fd31249 Update flags.js 2015-08-18 12:19:43 -06:00
Dynomity 31ccabe952 added flags.js 2015-08-17 22:25:39 -06:00
Dynomity 849fc1acf2 work in progress
created static file to store ICAO codes
2015-08-17 22:23:23 -06:00
Dynomity 37c58322e5 Merge remote-tracking branch 'origin/flags' into flags 2015-08-17 22:21:18 -06:00
Dynomity bb576566ca changed ICAO to Country in selected section 2015-08-17 22:20:13 -06:00
Dynomity d7bb5f10b5 Merge remote-tracking branch 'mutability/master' into flags 2015-08-17 17:32:03 -06:00
Dynomity ee36258f49 Create README.txt 2015-08-17 12:20:34 -06:00
Oliver Jowett e438e1e0c5 Fix decoding of even lat=0 + odd lat=0 which can have 3 results (-90, 0, +90) 2015-08-17 18:07:40 +01:00
Oliver Jowett 6d37952b14 Add tests for surface decoding at the poles/equator. 2015-08-17 18:06:37 +01:00
Oliver Jowett 3b4c5c5889 Merge pull request #63 from rgeissert/debian-package-fixes
Use invoke-rc.d to restart lighttpd as per Debian policy
2015-08-17 17:37:00 +01:00
Dynomity 3f4d35f04c add blank flag 2015-08-17 05:00:19 -06:00
Dynomity e907a068f2 Update gmap.html 2015-08-16 17:22:10 -06:00
Dynomity 54be82c50c Update script.js 2015-08-16 17:17:16 -06:00
Dynomity c3e3130da8 flag images
flag images in flags-tiny directory
2015-08-16 14:09:13 -06:00
Dynomity c62dda5136 adding country flags to ICAO listing
Requires addition of flag images as .png files stored in ~/flags-tiny.
I think I got them from http://www.iconarchive.com/category/flag-icons.html

This is my first attempt with github. Please bear with me!
2015-08-16 12:49:41 -06:00
Raphael Geissert 5eaa62d59c Use invoke-rc.d to restart lighttpd as per Debian policy 2015-08-08 13:47:05 +02:00
Oliver Jowett 8d815b7a9c faup1090 accepts/requires --stdout 2015-08-07 11:04:32 +01:00
Oliver Jowett b4490c7b47 Clear markers and don't color rows if the aircraft sees no positions for 60s,
even if they are still receiving other messages.

The marker/trail can be redisplayed by selecting the plane from the table.
2015-07-15 17:07:28 +01:00
Oliver Jowett 45d645a864 Default to not forwarding mlat messages. Add --forward-mlat option to enable it. 2015-07-03 21:56:23 +01:00
Oliver Jowett e5053ac5c9 Only set/reset position_from_mlat when we actually see position data.
Otherwise, if the position data times out on the dump1090 side, we'd
keep the last seen position on the webpage side but lose the mlat
status.
2015-06-29 15:51:42 +01:00
Oliver Jowett 32f87412d6 Show mlat positions differently in the detail pane. 2015-06-29 14:04:52 +01:00
Oliver Jowett de4e233969 When considering whether to suppress altitude messages, ignore mlat DF17s. 2015-06-29 12:45:50 +01:00
Oliver Jowett f1f76cb8e3 When receiving mlat, allow larger gaps between positions before plotting estimated tracks.
mlat positions aren't generally so frequent as proper ES, so they'd almost always plot
as estimated.
2015-06-29 12:44:19 +01:00
Oliver Jowett 98a55c8dec Tweak CPR rules for mlat messages, add some debug. 2015-06-29 12:43:58 +01:00
Oliver Jowett f6ff1c853b Show synthetic MLAT messages as such. 2015-06-29 12:42:50 +01:00
Oliver Jowett 1a3f65eaab Add --no-interactive, --show-only options to view1090
This turns it into a handy debug tool for looking at raw messages
from an existing running dump1090 without having to mess around with
a separate copy of dump1090 and netcat tunnels etc.
2015-06-29 12:41:55 +01:00
Oliver Jowett bd96d40e4e Display aircraft with mlat-derived positions with a different row color. 2015-06-29 10:47:29 +01:00
Oliver Jowett 51b5f4af24 Include mlatFlags in aircraft.json.
This requires expanding the line-buffer margin too as we can produce lines >256 chars now.
2015-06-29 10:46:37 +01:00
Oliver Jowett b793f83a29 Rewrite and fix heartbeat code.
The old logic had a number of problems, including:

 * sending heartbeats on all service types if any type needed
   a heartbeat
 * sending a heartbeat multiple times a second if there was a
   service type that was idle but didn't generate traffic when
   an empty message was sent (e.g. FATSV)

Rewrite it all so that heartbeats are explicitly tracked and handled
per service type, rather than by sending a dummy message.

Also switch to mode A/C messages for the beast/raw heartbeat, as
it's a bit more compact and less likely to mess with Mode S state
(an all-zeros Mode S message actually looks valid)
2015-06-29 10:06:13 +01:00
Oliver Jowett 803760ca80 Treat an all-zeros message as bad. 2015-06-29 00:50:19 +01:00
Oliver Jowett 75851778c0 Fix up filter population so it's not completely insane.
The logic for DF11 was completely broken and inverted. How did this ever work??

Actually, the broken version kinda works because the only types of message that
can yield an address that's not already in the ICAO filter are DF11/17/18.
So DF=17; DF=18; and DF=11 with IID=0 would pass the broken logic and populate the
filter. All other DFs would pass the broken test, too, but they can only ever
re-add entries that were already there.
2015-06-29 00:46:34 +01:00
Oliver Jowett 934dfee6a4 Change the mlat timestamp to something that doesn't need escaping. 2015-06-29 00:31:42 +01:00
Oliver Jowett 12a7d45e75 Mlat synthetic message detection.
Notice synthetic mlat messages by looking for messages with a magic
timestamp value. If they arrive, tag the derived data as mlat-derived.

Don't include mlat-derived output in FATSV output to avoid loops.
2015-06-28 20:04:09 +01:00
Oliver Jowett 8f08c1b87f Make faup1090 write to stdout, not listen on port 10001. 2015-06-28 19:59:49 +01:00
Oliver Jowett c7722f2b97 Guard against closing clients in a couple of places.
In particular, not guarding in flushWrites() meant that we
could end up trying to write to an uninitialized writer
(where writer->service == c->service == NULL) and crashing.
2015-06-26 21:29:54 +01:00
Oliver Jowett 8d1df036ae Don't use DF0/4/16/20 altitudes when DF17/18 altitudes are available.
The DF17/18 values are generally more trustworthy as they have full
CRC coverage. Errors in the CRC bits of a DF0/4/16/20 message can
result in the contained altitude being attributed to the wrong aircraft.
2015-06-26 20:43:46 +01:00
Oliver Jowett 5c2ec7106e Clean up dependencies.
Move ModeA/C demodulator to demod_2000 (decoding stays in mode_ac.c)
Remove dependency on interactive.c in stats.c
faup1090 then doesn't need interactive.c at all.
2015-06-26 18:36:14 +01:00
Oliver Jowett 99dd290352 Rebuild a basic faup1090 using the reworked network services bits.
This is a from-scratch reimplementation that should be functionally
equivalent to the Flightaware version that was based on dump1090_mr
and had its fingers deep in the network code. This version should be
a little less invasive / fragile..
2015-06-26 17:54:23 +01:00
Oliver Jowett 278448179d Factor out net services so they're not tied to a static array.
This lets different things dynamically create the services they need,
and sorts out the horrible hacks that view1090 used to make outgoing
connections. Now you can explicitly create a service and tell it to make
an outgoing connection.

This means that view1090 can now just set all the ports to zero (to disable
the listeners), do a normal net init, then explicitly construct the beast
input service without a listener and tell it to make a connection as needed.
2015-06-26 17:50:51 +01:00
Oliver Jowett 5fa039a2d4 Only require librtlsdr headers while we're compiling dump1090,
not the other helpers that don't use the dongle.
2015-06-26 17:49:21 +01:00
Oliver Jowett 656df98a76 Add --stats-range 2015-06-19 17:29:14 +01:00
Oliver Jowett e7e9cecc1a Add --throttle option.
This gives access to the existing throttling behaviour when reading
from a file with --interactive, without needing to actually have
--interactive.

This is useful when testing, as without --throttle samples will be
processsed much faster than real-time, which can produce different
results with e.g. aircraft/filter expiry times and position/speed checks.
2015-06-18 11:24:01 +01:00
Oliver Jowett 21bdc45bf0 Tweaks to noise measurements. 2015-06-16 10:13:25 +01:00
Oliver Jowett 7d4eaf6a48 Don't emit stale alt/speed/track/pos (more than 30s old) even if
they were updated since we last emitted a message.
2015-06-16 01:38:44 +01:00
Oliver Jowett 4f861f653a Track age of heading/speed/altitude; use this when deciding what to emit in FATSV format. 2015-06-15 23:13:04 +01:00
Oliver Jowett 03b53c2d29 Factor out the sample -> magnitude conversion code and make everything a little less sample-rate-dependent.
Add optional noise measurement (cheaper than the old version)
Add optional DC filter (expensive, not really needed with rtlsdr input)
2015-06-15 22:14:37 +01:00
Oliver Jowett f58ff14d7c Fix queueing/resending very old Mode A/C messages.
Fixes #47.
2015-06-07 23:00:24 +01:00
Oliver Jowett 03ba828f8d Rearrange position cleanup to be a bit more obvious.
Previously it forgot to advance to the next aircraft and only
happened to work because it cleared the position bitflags and so
the next iteration (on the same aircraft) would advance.
2015-06-07 12:07:08 +01:00
Oliver Jowett a60270e20e Don't hang if the ICAO hashtable fills up. 2015-05-30 01:09:41 +01:00
Oliver Jowett 079de99eec Add --iformat option that controls the format of the data read from --ifile.
This currently understands:

UC8 (original rtl_sdr format, 8-bit unsigned complex);
SC16 (16-bit signed complex, full width);
SC16Q11 (bladeRF native format: 16-bit signed complex with 11 bits of magnitude)
2015-05-29 18:22:41 +01:00
Saikrishna Arcot 05469fbff8
Add curl as recommends. 2015-05-04 11:11:06 -05:00
Oliver Jowett 0bd897cad1 Fix --mlat --raw stdout formatting on big-endian systems. 2015-04-19 00:57:24 +01:00
Oliver Jowett 4d697ac61d Emit capitalized hex in avrmlat output. 2015-04-18 11:21:09 +01:00
Oliver Jowett e9378fb1c5 Fix endian issues in timestamp input/output.
This affected Beast input/output, and AVR output in --mlat mode.

Works on a little-endian host, should work on a big-endian host but
I don't have one to test with.

Probably fixes #44.
2015-04-18 11:05:12 +01:00
Oliver Jowett ff094519a6 Fix interactive-mode delay timing when using --ifile. 2015-04-09 19:18:49 +01:00
Oliver Jowett 15ea5ba3da Rearrangements to the receive thread.
Magnitude conversion now happens immediately when sample data is
received, so there is no risk of newly received data clobbering old
data under CPU overload.
2015-04-09 18:51:31 +01:00
Oliver Jowett e6c81251bf Fix timestamp correction when sample blocks are dropped.
(Fixes #43)
2015-04-08 19:13:40 +01:00
Oliver Jowett 6148a05cef Raspbian doesn't do ${python:Depends} 2015-02-25 13:51:47 +00:00
Oliver Jowett e8ad60de6b Making progress output a bit friendlier. 2015-02-25 13:51:28 +00:00
Oliver Jowett 89ac9ad107 Mark this version as ~dev. 2015-02-25 13:17:20 +00:00
Oliver Jowett 60eab2284f Package changes to support the aircraft DB. 2015-02-25 13:16:54 +00:00
Oliver Jowett 8209267301 Avoid creating small child blocks, keep data in the parent where possible.
This reduces the number of blocks from 151 to 61.
2015-02-24 23:04:26 +00:00
Oliver Jowett da2fff8531 Proof of concept for an aircraft metadata DB. 2015-02-24 21:51:30 +00:00
Oliver Jowett d7c5047fd3 Fix crash when requesting nonexistent extensionless files
(but only if HTMLPATH does not contain a '.')

Clean up overuse of strstr.

(based on 259ce08f81eaaaa087b6b1994fce7dde81820c52)
2015-02-23 00:11:55 +00:00
Oliver Jowett e1d262d992 Add --show-only for extracting messages from a single plane. 2015-02-22 23:01:54 +00:00
Oliver Jowett b804359077 Initialize category. 2015-02-22 20:11:11 +00:00
Oliver Jowett 87bd16812a Add formatter.js to conffiles. 2015-02-22 17:03:47 +00:00
Oliver Jowett 7fbdde156a Change map icon based on aircraft category.
This only has different icons for the "rotorcraft" and "light"
categories at the moment - all others are the default plane icon
at different scales.
2015-02-22 17:02:23 +00:00
Oliver Jowett 7bd2bcc0a2 Move color settings into config.js 2015-02-22 12:27:01 +00:00
Oliver Jowett 8f3be2cd79 Decode aircraft category, export in aircraft.json.
Closes #2.
2015-02-22 12:15:26 +00:00
Oliver Jowett 8fabfcb94f Merge branch 'm30164-title_numbers' 2015-02-22 11:53:28 +00:00
Oliver Jowett 268599a211 Tweaks to title mangling:
* use PageName, not literal "DUMP1090"
 * use document.title directly, not a selector
 * include number of positionless aircraft too
 * rename the config options
 * some simplification of the changes
2015-02-22 11:51:58 +00:00
Oliver Jowett 288a8242dd Merge branch 'title_numbers' of https://github.com/m30164/dump1090 into m30164-title_numbers 2015-02-22 11:35:59 +00:00
Oliver Jowett df64abe433 Move special-character definitions to formatter.js. 2015-02-22 01:29:02 +00:00
Oliver Jowett 0367429b9d Merge branch 'm30164-Unit_settings' (closes: #27) 2015-02-22 01:23:26 +00:00
Oliver Jowett 5c1cf53316 Simplify settings down to just Metric / ShowOtherUnit.
Factor out some common code.
2015-02-22 01:22:05 +00:00
Oliver Jowett 082e973990 Merge branch 'Unit_settings' of git://github.com/m30164/dump1090 into m30164-Unit_settings 2015-02-22 00:55:46 +00:00
Oliver Jowett e7d7fd549c Fix off-by-one error in Beast-format input.
This would mangle messages if the first byte of a message ended up
as the last byte returned by a read() call - it would read beyond
the end of the buffer, decide the message was damaged, and then run
off into the message data looking for a new delimiter. Sometimes
that would work (only dropping one message), but sometimes it would
run into data that happened to look like a message start but
actually wasn't, and then try to interpret that, leading to completely
bogus message data being read.

Fixes #29.
2015-02-21 23:50:35 +00:00
Oliver Jowett 8e9220e330 Quick prototype of color-by-altitude. 2015-02-21 18:41:59 +00:00
m30164 297d3b0125 Number of planes and messages in title
Simple addition to display the current number of planes and messages in
the title.
2015-02-20 11:42:29 +01:00
m30164 a531327533 Added extended unit settings
Added some code to enable the user to configure unit selection in a more
detailed fashion. you can now select either metric or imperial, or both,
and even set which one of those should be displayed first.
2015-02-20 00:09:03 +01:00
Oliver Jowett ab8c4db85b Fix edge cases when specifying the user to run as.
* check the username fits the format expected by adduser;
 * don't allow root;
 * if the user exists, don't try to create it; usually, this is
   harmless, but it fails if the user exists with a UID outside the
   normal range for system users.

Fixes #24.
2015-02-19 22:41:39 +00:00
Oliver Jowett f391bf4b22 Release changelog. 2015-02-19 19:41:44 +00:00
Oliver Jowett e0f167b703 Fix json syntax error. 2015-02-19 19:12:06 +00:00
Oliver Jowett f6d2f3dfff More CPR stats. 2015-02-19 18:53:11 +00:00
Oliver Jowett 46ad97da15 More changelogging. 2015-02-19 12:11:30 +00:00
Oliver Jowett 65e7d32390 Mark all HTML/Javascript as conffiles.
Closes #15.
2015-02-19 12:05:53 +00:00
Oliver Jowett ecd22d82a2 Make non-pbuilder debuild happier. 2015-02-19 12:03:08 +00:00
Oliver Jowett 8fa7209aa1 Changelog updates for 1.14. 2015-02-19 12:02:45 +00:00
Oliver Jowett 7cc9438b2d Speed check improvements. Entirely invalidate position messages that look wrong. 2015-02-18 18:26:23 +00:00
Oliver Jowett 44302bb199 Fix NaN in greatcircle calc if positions are identical.
Bail out early if there's a global CPR decoding error so we don't try
to do range/speed checks on a position of (0,0)
2015-02-18 01:53:47 +00:00
Oliver Jowett bfe2cb0336 NUCp tracking and CPR position sanity checks.
Track NUCp when we compute positions.

Do speed checks when we have an updated position with the same or worse NUCp
before accepting the new position. Don't do speed checks on new postions if
they improve NUCp - assume that the new position is better.

Include NUCp in aircraft.json

Gather stats on reasons for rejecting CPR data due to range/speed check failures.

Expire old positions if we have had no updates for 60 seconds.

Closes #16, closes #17.
2015-02-18 00:12:35 +00:00
Oliver Jowett 38845c2447 Rearrange main loop so that --net-only isn't quite such a special case. 2015-02-17 21:44:30 +00:00
Oliver Jowett 0a055c34d0 Log timestamped messages on startup/shutdown. 2015-02-17 21:43:17 +00:00
Oliver Jowett dcdfd2acab Catch SIGTERM, log on signals.
Fixes #22.
2015-02-17 21:41:40 +00:00
Oliver Jowett 342eafd438 Include timestamps on USB connect/disconnect logging.
Fixes #21.
2015-02-17 21:40:26 +00:00
Oliver Jowett af4f81caf7 Include timezone in stats output. 2015-02-17 21:35:23 +00:00
Oliver Jowett 03e096475c Wait for at most 100ms for more data from the rx thread, so that we do not starve background tasks if the rx thread blocks (e.g on USB disconnect).
Fixes #20.
2015-02-17 21:07:36 +00:00
Oliver Jowett aee837c903 Start with --nicelevel -5 to reduce the chance of dropped buffers, except in --net-only mode.
Closes #19.
2015-02-11 21:20:31 +00:00
Oliver Jowett 967a3e9558 If maxRange is >= 360NM, don't do receiver-centered local CPR at all. 2015-02-11 12:10:40 +00:00
Oliver Jowett 7849e1019d Init start/end on all stats so the json output looks sensible for the first minute. 2015-02-11 01:14:21 +00:00
Oliver Jowett 6fbeae070c Handle long refresh rates better, don't draw all tracks as dotted. 2015-02-11 00:15:48 +00:00
Oliver Jowett 2ba56231a6 Do an initial data fetch immediately (useful if the refresh interval is long). 2015-02-11 00:15:21 +00:00
Oliver Jowett 849697f84c Fix integer overflow in stats output. 2015-02-11 00:14:28 +00:00
Oliver Jowett af382ac79c Fix max flush interval to be in milliseconds. 2015-02-10 23:43:48 +00:00
Oliver Jowett f9ed7e4a97 More time_t -> milliseconds conversions.
This lets us support fractional net flush times among other things, which is handy.
2015-02-10 22:24:22 +00:00
Oliver Jowett 7053ad02da Make aircraft tracking use milliseconds everywhere. 2015-02-10 21:49:37 +00:00
Oliver Jowett 686d433b1f Prune dead timestamp fields from aircraft state. 2015-02-10 21:33:01 +00:00
Oliver Jowett 474fe45256 Don't mark undecodable altitudes as ALTITUDE_VALID when decoding. 2015-02-09 22:53:18 +00:00
Oliver Jowett 54677f3ae0 Don't try to correct >1 error in DF11.
We already do this check when scoring a message for the demodulator,
but there are other paths that can feed us a message so also do the
check in the main decode path.
2015-02-09 22:51:34 +00:00
Oliver Jowett f19eee898b Use the right inter-CPR max interval for surface position messages. Fixes #18. 2015-02-09 14:17:31 +00:00
Oliver Jowett 9fd0c822f6 Extract NUCp from message type; needed for #16. 2015-02-09 14:14:12 +00:00
Oliver Jowett e7e7f9e7c2 Only display altitude when dumping position messages if it is valid. 2015-02-09 14:11:04 +00:00
Oliver Jowett 07a39331c9 Changelog mostly to bump the version to reduce confusion. 2015-02-08 23:11:50 +00:00
Oliver Jowett 25ac2d044d Increase the onehit TTL a bit, 30s is a bit too aggressive. 2015-02-08 22:46:44 +00:00
Oliver Jowett b313834338 Make the is_number regex accept numbers beginning with -0
Also ends up simpler, too - originally I was trying to avoid accepting
e.g. "+0" or "-0" but that's not really a big deal.

Fixes #14
2015-02-08 22:44:02 +00:00
Oliver Jowett a49b5b8830 Add stats for total aircraft tracks and tracks that have only a single message. 2015-02-08 18:47:39 +00:00
Oliver Jowett f1201a0069 Third time lucky? 2015-02-08 18:17:33 +00:00
Oliver Jowett b31709a278 Whoops, remove stray debugging that was left in. 2015-02-08 18:16:49 +00:00
Oliver Jowett 1e817ab9e4 Merge pull request #12 from jburgess777/add-view1090-to-gitignore
Add view1090 to gitignore
2015-02-08 18:08:26 +00:00
Oliver Jowett bdefa42956 Merge pull request #11 from jburgess777/add-oversample-to-help
Add --oversample option to help text
2015-02-08 18:07:23 +00:00
Oliver Jowett 4ecd6958a1 If we squelch the first message from an aircraft, emit it when we see a second message.
This is possible now that the SBS output doesn't rely on the global block timestamp;
the output will look like this:

MSG,8,111,11111,4AC954,111111,2015/02/08,17:57:53.917,2015/02/08,17:57:53.936,,,,,,,,,,,,0
MSG,7,111,11111,392AEB,111111,2015/02/08,17:57:53.744,2015/02/08,17:57:53.936,,15375,,,,,,,,,,0
MSG,8,111,11111,392AEB,111111,2015/02/08,17:57:53.917,2015/02/08,17:57:53.936,,,,,,,,,,,,0
MSG,6,111,11111,800387,111111,2015/02/08,17:57:53.919,2015/02/08,17:57:53.936,,,,,,,,4745,0,0,0,0

where the "receive timestamp" (first time column) goes backwards to reflect the original reception
time of the delayed message, but the "forwarded timestamp" (second time column) reflects the actual
forwarding time.
2015-02-08 18:00:18 +00:00
Oliver Jowett c0af448efa uint64_t (even at 12MHz) isn't going to overflow any time soon, don't worry about wrapping. 2015-02-08 17:59:20 +00:00
Oliver Jowett 9c2f236463 Object files depend on *.h 2015-02-08 17:58:46 +00:00
Oliver Jowett 4e177c2d64 Store computed reception time in the message struct so we don't rely on
the message being emitted immediately.

Fix computation of reception time so it's more sensible (the block timestamp
is some time after reception of the _end_ of the block, not the start) - this
means that message-emission times are always later than message-reception
times in SBS output, which is a bit more sensible.

Use clock_gettime in preference to ftime.
2015-02-08 17:46:01 +00:00
Oliver Jowett 1584955080 Be more aggressive about removing aircraft where we have seen only 1 message. 2015-02-08 14:37:35 +00:00
Oliver Jowett 20407e5378 Don't emit SBS output with non-ICAO addresses (fixes #9) 2015-02-08 14:30:10 +00:00
Oliver Jowett 899c51ce85 Only emit network messages once we have seen two of them
(except in --net-verbatim mode, where we emit them all)

Move aircraft tracking into track.[ch].

Clean up references to "interactive mode" when tracking
aircraft - we always track aircraft, even in non-interactive
mode.
2015-02-08 14:27:03 +00:00
Jon Burgess b246bdcab4 Add view1090 to gitignore 2015-02-07 23:25:43 +00:00
Jon Burgess e1e5acbdbc Add --oversample option to help text 2015-02-07 23:15:12 +00:00
Oliver Jowett 704d8aaffb Don't try to log signal peak power if no peaks recorded. 2015-02-06 13:27:47 +00:00
Oliver Jowett 965ac96493 Update bestscore even if decoding fails so we register the number of "unknown ICAO" messages correctly. 2015-02-06 13:11:41 +00:00
Oliver Jowett 9381a20198 Support more DF18 message formats. Test for the IMF bit where appropriate.
Fixes #4.
2015-01-29 23:08:33 +00:00
Oliver Jowett ffd6690063 Update README-json.md 2015-01-28 20:44:41 +00:00
Oliver Jowett f593d8672d Document some of the json 2015-01-28 20:15:14 +00:00
Oliver Jowett 4dbedecc1e Fix history loading if receiver.json says history:0 2015-01-25 21:54:40 +00:00
Oliver Jowett 02f07ac7bf Release changelog. 2015-01-25 16:45:05 +00:00
Oliver Jowett 4b0bc4cee9 Make 2.4MHz sampling the default for new installs. 2015-01-25 16:11:34 +00:00
Oliver Jowett 09b6b3aa8c Fix some lintian warnings. 2015-01-24 01:08:05 +00:00
Oliver Jowett c1ac4d1036 Update GPL coverage. 2015-01-24 01:04:45 +00:00
Oliver Jowett 26feb1d078 Add some testing code that looks for ambiguous syndromes that
could confuse the partial correction used in DF11.

That code shows that yes, there are ambiguous syndromes in the
2-bit correction case only, so disable corrections of more than
1 bit in DF11.
2015-01-23 21:59:31 +00:00
Oliver Jowett 5ac90e30a8 Changelog. 2015-01-23 21:26:57 +00:00
Oliver Jowett dcd9f0b1e7 Link ICAO to airframes.org (complete with horrible javascript form-submission workaround) 2015-01-23 19:17:07 +00:00
Oliver Jowett 245bbd8b97 Report total, not latest-minute, message count in aircraft.json so that
the webmap value doesn't jump around over a reset.
2015-01-23 17:40:03 +00:00
Oliver Jowett c5b61a33fd Oops, another compile error, sigh. 2015-01-23 02:11:44 +00:00
Oliver Jowett c07e45a4c8 Report CPU in integer milliseconds, makes it a bit easier to process. 2015-01-23 02:03:57 +00:00
Oliver Jowett df5e41363a Fix compile error. 2015-01-23 01:49:14 +00:00
Oliver Jowett 5b40377b98 Measure CPU for demodulator, read thread, and background tasks individually. 2015-01-23 01:22:22 +00:00
Oliver Jowett 9deac8d894 Continuing to try to work around libusb/librtlsdr problems. 2015-01-23 01:20:22 +00:00
Oliver Jowett 4fb607a826 Noise floor measurement is too expensive to be worth it, disable it. 2015-01-22 23:38:21 +00:00
Oliver Jowett dc8891e0ba Reduce the demodulation length properly when we see a 56-bit DF. 2015-01-22 23:34:47 +00:00
Oliver Jowett d76b8948b3 Make doubleclick-follow also set zoom, like clicking the follow arrow does. 2015-01-22 23:12:41 +00:00
Oliver Jowett 5020d75b9e Move setting of CF earlier so we can use its value while decoding AA.
(Needed to notice non-ICAO addresses in TIS-B)
2015-01-22 22:19:38 +00:00
Oliver Jowett 07c4f045aa Fix italicizing of non-ICAO rows 2015-01-22 22:19:17 +00:00
Oliver Jowett f76842d186 Doubleclick on plane marker to follow, too. 2015-01-22 21:35:59 +00:00
Oliver Jowett 53203a5f71 Make the arrow bold/unbold to reflect current follow mode. 2015-01-22 21:31:02 +00:00
Oliver Jowett a4360cd775 Move the "follow" button to an arrow by the callsign.
Also make the callsign clickable to follow.
2015-01-22 21:30:37 +00:00
Oliver Jowett 3040609816 Doubleclick on a table entry to follow that aircraft. 2015-01-22 21:28:35 +00:00
Oliver Jowett eb023ff1d9 Don't include latest in 1/5/15 min totals, it's a bit confusing.
This means the 1/5/15 min values may reflect a period that ended
up to 1 minute ago, but the length of the measured period is always
as expected i.e. 1/5/15 mins.
2015-01-22 20:45:53 +00:00
Oliver Jowett fe0a87a588 Fix remote_received_modes counter. 2015-01-22 20:40:30 +00:00
Oliver Jowett c8025700e5 Emit all stats in stats.json. 2015-01-22 20:18:51 +00:00
Oliver Jowett 008ae926e7 Add --net-verbatim, which forwards the original uncorrected message to net clients,
not the corrected version. Then the client can make its own policy decisions about
whether to accept and correct the damaged messages.
2015-01-22 19:56:38 +00:00
Oliver Jowett a59077a370 Stats overhaul. 2015-01-22 19:49:19 +00:00
Oliver Jowett 6672d92d9e Don't double up the ICAO display if there's no callsign. 2015-01-22 17:35:20 +00:00
Oliver Jowett d3537ec139 When first following a plane, zoom in if we are zoomed far out. 2015-01-22 16:14:32 +00:00
Oliver Jowett 3fd2032f49 Make altitude column indicator consistent with the detailed info. 2015-01-22 16:14:11 +00:00
Oliver Jowett 09c50fff4d Show vertical rate indicators next to altitude. 2015-01-22 16:09:19 +00:00
Oliver Jowett ba8a8935be Move ICAO for the selected plane into the header line.
Put RSSI in the selected info box where ICAO used to be.
2015-01-22 15:31:35 +00:00
Oliver Jowett ffe03fe749 Track RSSI in PlaneObject. 2015-01-22 15:31:10 +00:00
Oliver Jowett b77d52bd1f Include recent RSSI in aircraft output. 2015-01-22 15:30:34 +00:00
Oliver Jowett 89d6b64747 Treat signal level in network messages as a (RMS) amplitude, since that
is what was previously done and it gives us better range for small signals.

Means a sqrt() call on beast output, but this shouldn't be too bad as
it's only done once per message.
2015-01-22 15:28:35 +00:00
Oliver Jowett fac838b9ad Rearrangements to infoblock layout. 2015-01-22 14:44:32 +00:00
Oliver Jowett 6daf116b40 Clean up config.js a bit, support configuring page name and site name. 2015-01-22 14:33:42 +00:00
Oliver Jowett b78b28d95f Add a "follow" link to the selected plane info. 2015-01-22 14:17:12 +00:00
Oliver Jowett 35e0364670 Fix compile errors. 2015-01-22 13:29:13 +00:00
Oliver Jowett 70e8579850 Simple filter for spurious messages that make it past checksum:
don't show aircraft until we have seen 2 messages from them.
2015-01-22 13:22:16 +00:00
Oliver Jowett 7500cabb08 Show rows with non-ICAO addresses in italic. 2015-01-22 13:21:47 +00:00
Oliver Jowett af3eb3df2b Move to a simpler versioning scheme (the one derived from upstream
is going to break the ordering that Debian expects very soon).

When building from source not via debian/rules, derive a version from
git describe.
2015-01-22 13:19:15 +00:00
Oliver Jowett ada188a1c8 Changed my mind, put the non-ICAO flag bit in the address itself
since we have 8 bits spare, so there's no chance of confusing it
with an ICAO address, and we can safely use the filter table to match
future messages without also matching equivalent ICAO addresses.
2015-01-22 12:30:12 +00:00
Oliver Jowett 35551b4455 Don't emit FATSV output for non-ICAO addresses. 2015-01-22 12:18:46 +00:00
Oliver Jowett 6e1315e3a6 Flag non-ICAO addresses in json output. 2015-01-22 12:18:14 +00:00
Oliver Jowett d0605629b6 Avoid zero signalLevel. 2015-01-22 11:40:52 +00:00
Oliver Jowett 9a91507583 Flag non-ICAO addresses, display them differently in interactive mode. 2015-01-22 11:14:22 +00:00
Oliver Jowett 34ae2c7349 Make sure to clear address. 2015-01-22 11:13:54 +00:00
Oliver Jowett 04eff1778f Use the right field for CF in DF 18 2015-01-22 10:59:11 +00:00
Oliver Jowett 7850848ef7 Export a few stats via JSON. 2015-01-22 01:21:53 +00:00
Oliver Jowett 19082d92ea Measure signal power / noise power (at least in 2.4MHz mode).
Switch signalLevel back to a power measurement, don't put SNR in there.
But make it a 0.0 - 1.0 double so we're not scaling everywhere.

Adjust for the amplitude offset when calculating power.

Adapt everything else to the new scheme.
2015-01-22 01:01:39 +00:00
Oliver Jowett 5beecb9f4f Disable overlay control as it seems to cause more problems than it solves
at the moment (aircraft randomly appearing to be on the ground due to
CRC errors, etc)
2015-01-22 00:59:44 +00:00
Oliver Jowett 20456a83fd Ditch SNR calcs too. 2015-01-21 19:10:07 +00:00
Oliver Jowett 00e232cc4f Try unrolling the inner loop to speed things up. 2015-01-21 19:03:51 +00:00
Oliver Jowett ef098a2461 Import new 2.4MHz demodulator from experimental branch. 2015-01-21 13:32:17 +00:00
Oliver Jowett 0493248425 Minor cleanups / comments. 2015-01-21 12:55:46 +00:00
Oliver Jowett a33e4388c9 Add scoreModesMessage() 2015-01-21 12:55:24 +00:00
Oliver Jowett fc87a232b4 Return non-NULL errorinfo if there are no errors to diagnose. 2015-01-21 12:54:27 +00:00
Oliver Jowett 2a1a2a0a71 Fix (maybe) JSON escaping.
I've obviously never tested this code!
2015-01-21 11:58:51 +00:00
Oliver Jowett cae20a8060 Escape flight name in JSON in case it has odd characters. 2015-01-21 11:56:27 +00:00
Oliver Jowett ebae590653 Use MODES_NOTUSED for unused args. 2015-01-21 11:54:55 +00:00
Oliver Jowett 7c64f27c22 Remove unused user latitude/longitude defines. 2015-01-21 11:53:45 +00:00
Oliver Jowett 8ce92f126a More logging for Comm-B messages. 2015-01-21 01:21:32 +00:00
Oliver Jowett 5e522fe8db Decoder cleanups from experimental branch. 2015-01-21 00:23:48 +00:00
Oliver Jowett 0433ed3f5d icao_filter.[ch] from the experimental branch. 2015-01-20 23:53:26 +00:00
Oliver Jowett 270a22e06a CRC reimplementation to be byte-at-a-time table-driven.
Also be smarter about error correction, avoiding ambiguous cases
when --aggressive is specified.
2015-01-20 23:04:05 +00:00
Oliver Jowett 0d3fcfff2e Remove obsolete TODO file. 2015-01-20 18:42:20 +00:00
Oliver Jowett ed4d481772 Import CPR changes from experimental branch. 2015-01-20 18:41:44 +00:00
Oliver Jowett b9b76da02d Stats rearrangement, based on experimental branch changes. 2015-01-20 17:16:35 +00:00
Oliver Jowett e02a2cdd44 GPL. 2015-01-20 16:49:01 +00:00
Oliver Jowett f753c2d9fe Separate 2.4MHz demodulator into its own file. 2015-01-19 23:50:25 +00:00
Oliver Jowett a6542b505b Separate out 2MHz demodulator + support functions to a separate file. 2015-01-19 23:47:51 +00:00
Oliver Jowett 014205324a Remove dead test code. 2015-01-19 23:43:15 +00:00
Oliver Jowett 07df054590 Move CRC code to a separate file. 2015-01-19 23:41:26 +00:00
Oliver Jowett 721412dc9b Changelog. 2015-01-19 23:29:07 +00:00
Oliver Jowett 5e80a11934 Fix stable sort of rows with no sortable values (would cause "jumping" rows at the end of the table) 2015-01-19 23:28:04 +00:00
Oliver Jowett 881cb8167d Release changelog. 2015-01-17 21:04:10 +00:00
Oliver Jowett 5cbe5d909b Don't cache receiver.json as it may change more frequently now (history size). 2015-01-17 21:02:17 +00:00
Oliver Jowett 971e5754ff Try to work around a libusb crash on exit after SIGINT. 2015-01-17 19:23:57 +00:00
Oliver Jowett f0fe4663d5 Oops, helps to actually commit the fix too.. 2015-01-17 18:26:36 +00:00
Oliver Jowett d1f274d469 Avoid a (rare) divide-by-zero crash in 2MHz --phase-enhance. 2015-01-17 18:26:06 +00:00
Oliver Jowett 4a66a31839 Changelog. 2015-01-17 12:31:52 +00:00
Oliver Jowett f71f93464b Always sort missing values at the end of the table, even in a descending sort.
Simplify the sorting a bit by separating out the "extract value to compare" logic.
2015-01-17 12:27:13 +00:00
Oliver Jowett 8f1b8566d4 Update changelog. 2015-01-16 20:37:55 +00:00
Oliver Jowett bfcfb1fdcb Fix sort-by-message-count.
(cherry picked from commit 9f40dbaf786c69aaf459c69b2058bba9cd30569f)
2015-01-16 20:34:03 +00:00
Oliver Jowett e68949bdb3 Write an accurate value for the history count, so the progress bar is correct.
(cherry picked from commit 0919700293e34f5a93a4407d33e1e56c0ae0d13c)
2015-01-16 20:33:40 +00:00
Oliver Jowett dd734debc3 Add a loading progress bar, as it can be slow with internal webserver (100ms/request)
plus large history (120 requests).

(cherry picked from commit e1b0b7a5b6759bb7a59536efcc4d6652d92dda16)
2015-01-16 20:33:32 +00:00
Oliver Jowett 870233977c Less aggressive history settings.
(cherry picked from commit d41090c57cb37352b7689e36af55cdb89486c230)
2015-01-16 20:33:23 +00:00
Oliver Jowett c7204ec6ab Support image/gif content type
(cherry picked from commit f4b38a62f69d0df2bb5d3a87979e38d76249b80a)
2015-01-16 20:33:08 +00:00
Oliver Jowett 6458cfd2fe Load history when the map is initialized.
This can take a few seconds, so add a loading spinny while it loads.

(cherry picked from commit 8d3fdcc1625278a25a289dee33ef6b8eaccfd0ff)
2015-01-16 20:32:55 +00:00
Oliver Jowett 1db63ebc65 Add generation of history JSON.
Add support for URL handlers that match a path prefix.

(cherry picked from commit 38faa510cb881cbf9d2a0a85bbde61130b5259e7)
2015-01-16 20:31:59 +00:00
Oliver Jowett b1bfb4d520 Rationalization of JSON output. Pass actual URL path to URL handler.
(cherry picked from commit becce8d69a6e6cee38d4fdb78b5a4e25d570baea)
2015-01-16 20:30:41 +00:00
Oliver Jowett 63fb121d1c Status messages in HTTP responses.
(cherry picked from commit 820528b4ad7f3963199718205724cdf3ac97b113)
2015-01-16 20:28:36 +00:00
Oliver Jowett 10c372f528 Display stats on exit in --net-only mode.
(cherry picked from commit ec252d77deb2b345a8561cba13965d5ef8ab0a83)
2015-01-16 20:27:48 +00:00
Oliver Jowett e701f883b3 Do tuner gain setting properly.
(cherry picked from commit c06a537c8143af8e363fde677043053cefff1612)
2015-01-16 20:25:45 +00:00
Oliver Jowett e54b290601 Release changelog. 2015-01-14 01:17:57 +00:00
Oliver Jowett 62ec7796d0 Require that the JSON refresh interval is at least 1, as it is used
to control the webmap refresh rate even if JSON files are not being written.
2015-01-14 01:15:54 +00:00
Oliver Jowett dc92cfb927 Restart lighttpd on package upgrade if we changed its config files. 2015-01-14 00:34:06 +00:00
Oliver Jowett 371f6bb5d4 Changelog. 2015-01-13 22:02:39 +00:00
Oliver Jowett 72bfc31458 Display message rate (30 sec average) on the webmap.
(cherry picked from commit 848af78be685c6e2a26d0b30e9f385696201a2c4)
2015-01-13 22:01:53 +00:00
Oliver Jowett 41d8a79041 Changelog. 2015-01-13 21:53:48 +00:00
Oliver Jowett fefce7b4bd Add --max-range parameter. Use it for relative position limits, and to discard bad position results.
(cherry picked from commit 0d725508f78cb2fd7759efbb66b45b867d6f7722)
2015-01-13 21:53:12 +00:00
Oliver Jowett 8b56cd104f Changelog. 2015-01-13 21:41:23 +00:00
Oliver Jowett 4c8993865e Everything depends on dump1090.h, tell make about it.
(cherry picked from commit e1693ebe39a92422a0b6af56f307fc6c9288ad73)
2015-01-13 21:39:40 +00:00
Oliver Jowett 165f98a567 Fix hanging exit on control-C.
(cherry picked from commit e6f8283946cc3150bcba2d8b3cbab11f5d509308)
2015-01-13 21:37:45 +00:00
Oliver Jowett 2627933963 Changelog. 2015-01-12 16:31:22 +00:00
Oliver Jowett 8d0d16c30a When sanity-checking relative CPR results, use the correct relative
location (which may not be the aircraft location).

I suspect this sanity check is, in fact, redundant now that the
rest of the algorithm has had some bugs fixed; it should only
produce results within half a cell by definition.
2015-01-12 16:29:24 +00:00
Oliver Jowett 583984af8a Use floor() not trunc() in relative CPR decoding.
The comment saying to use trunc() is wrong; the original algorithm
is correct.
2015-01-12 16:28:10 +00:00
Oliver Jowett bebc00c257 Fix quadrant selection for global CPR surface position decoding. 2015-01-12 16:26:05 +00:00
Oliver Jowett e1d2af42bb CPR relative decoding: avoid truncation when finding the fractional
position of the reference position within a lat/lng zone.
2015-01-12 16:16:32 +00:00
Oliver Jowett 2febe75ce7 Changelog. 2015-01-12 01:19:43 +00:00
Oliver Jowett fa4c85eba5 Another bug found by valgrind. 2015-01-12 01:19:25 +00:00
Oliver Jowett 272efcbdc4 Fix thinko in skipping over decoded message samples. 2015-01-12 01:00:05 +00:00
Oliver Jowett f72fc3dbee Fix a couple of problems found by valgrind. 2015-01-12 00:56:51 +00:00
Oliver Jowett 0b5aac47c4 Change plane color if we have not seen a recent position update
(previously, any type of message was enough).
2015-01-11 12:15:54 +00:00
Oliver Jowett 55a10e6685 Changelog. 2015-01-11 12:12:58 +00:00
Oliver Jowett 019fd1fb06 Tweak the column widths in the infoblock slightly. 2015-01-11 12:12:28 +00:00
Oliver Jowett 0ccb5cc48e Tweak wordwrap on the infoblock. 2015-01-11 12:02:25 +00:00
Oliver Jowett 2f2803a775 Fix UTC clock display in non-UTC timezones. 2015-01-11 11:54:17 +00:00
Oliver Jowett 35e5088529 Fix initial map centering thinkos. 2015-01-07 23:54:54 +00:00
Oliver Jowett 94f62e5b5f Simplify sort functions, fix stable sort in the descending case. 2015-01-07 22:16:49 +00:00
Oliver Jowett b639fb9107 Don't display a track of "0" for aircraft with no heading data. 2015-01-07 22:14:50 +00:00
Oliver Jowett 4a04e4d46d Changelog updates. 2015-01-07 21:42:57 +00:00
Oliver Jowett 86b59e7bd9 Don't need to stash ICAO on the marker now that we're binding the event listener function directly. 2015-01-07 21:15:56 +00:00
Oliver Jowett b4de83090d Don't update icao in updateData, it should never change. 2015-01-07 21:15:34 +00:00
Oliver Jowett 25ff88c252 Only reset marker title if it changes. 2015-01-07 21:03:26 +00:00
Oliver Jowett 0f1c0778f2 Disable lighttpd's stat cache in the sample config. 2015-01-07 19:01:56 +00:00
Oliver Jowett 2c0fb752e1 Add the missing div used to display errors. 2015-01-07 18:44:45 +00:00
Oliver Jowett 93aedbe15c Tell the user about AJAX errors.
Set AJAX options: 5s timeout, no caching.
Don't spool up a second request while the previous one is in progress.
If we repeatedly see the same receiver timestamp, warn the user that the JSON isn't being updated.
2015-01-07 18:43:08 +00:00
Oliver Jowett 97ca1c77e7 Add some notes to config.js 2015-01-07 18:41:38 +00:00
Oliver Jowett 0976d12b88 Ditch any query strings in HTTP requests before handling them,
to allow AJAX requests to tack on a query string to avoid caching.
2015-01-07 18:40:55 +00:00
Oliver Jowett b2b0aa9afe Rearrangements to clock layout.
Provide UTC and last-receiver-update clocks.
2015-01-07 18:39:19 +00:00
Oliver Jowett e6a70345b5 Remove options / extension support (no plans to work on those in the current form). 2015-01-07 17:37:34 +00:00
Oliver Jowett 139ed5cb36 Turn on strict mode, fix a few errors. 2015-01-07 17:35:32 +00:00
Oliver Jowett df79f7c989 Fix up selected vs is_selected. 2015-01-07 17:32:20 +00:00
Oliver Jowett 29509d9633 Make PlaneObject a class.
Rearrange internal storage of positions.
Maintain sitedist within PlaneObject, not externally.
Clean up speed/dist/etc formatting.
Show both metric & imperial values in the plane detail infobox.
2015-01-07 17:18:33 +00:00
Oliver Jowett 58e5485c2a Stylistic cleanups. Unify special squawk data. 2015-01-07 16:32:58 +00:00
Oliver Jowett feb8c55bac Display the number of history points stored.
Rejuggle how markers are handled so that we avoid creating lots of new icons all the time.
Rearrange reaping / update times so that it is all based on timestamps from the receiver.
2015-01-07 01:19:05 +00:00
Oliver Jowett 9996b7c9fb Zoom in a bit more by default. 2015-01-07 01:18:36 +00:00
Oliver Jowett 43d29389f2 Lots more map work, mostly around switching from "construct a big HTML string"
to working directly with the DOM to update the table / selected plane info.
Seems to speed things up (and deflicker them) a lot.

Also stable sorts, allow disabling the clocks, draw ground tracks in a different
color, put "last seen" info on the selected plane infobox, if position updates
are infrequent then combine them into a single estimated line so that dash
placement works properly, probably a bunch of other things..
2015-01-06 20:15:25 +00:00
Oliver Jowett e8a62293c2 More WIP on the webmap, mostly fixing up track history. 2015-01-06 01:00:44 +00:00
Oliver Jowett 1f06abf67d WIP webmap cleanup 2015-01-05 23:20:03 +00:00
Oliver Jowett 99bca13844 Release changelog. 2015-01-04 20:23:30 +00:00
Oliver Jowett 43ec58c78e Remove dead tracking code related to the removed PlanePlotter feed. 2015-01-04 20:09:38 +00:00
Oliver Jowett 76474f58ab Fix warnings. Add -Werror so they break the build in future. 2015-01-04 20:08:33 +00:00
Oliver Jowett 14a8e71629 Version bump to reflect upstream version. 2015-01-04 12:32:36 +00:00
Oliver Jowett 66c088fa70 Release changelog. 2015-01-02 22:53:58 +00:00
Oliver Jowett 69532b3c53 Center the webmap on the receiver location.
Mark config.js as a conffile, so user changes won't get overwritten.
2015-01-02 22:48:27 +00:00
Oliver Jowett 85eee61358 Oops, one unsaved file. 2015-01-02 22:34:35 +00:00
Oliver Jowett 07bc762055 Notice if we lose the RTLSDR device and reconnect.
Fix some of the more glaring pthread bugs.
2015-01-02 22:29:29 +00:00
Oliver Jowett 5dd1c39710 Release changelog. 2014-12-30 17:09:44 +00:00
Oliver Jowett 9d0df29dbb Fix postinst handling of LOG_DECODED_MESSAGES. 2014-12-30 17:08:55 +00:00
Oliver Jowett a9ca260e76 Add support for LOG_DECODED_MESSAGES option to log all messages (disables --quiet). 2014-12-30 16:40:15 +00:00
Oliver Jowett 6e3238d303 Release changelog. 2014-12-30 00:01:58 +00:00
Oliver Jowett 9356c899ad Add Provides: fatsv-data-source 2014-12-29 22:59:47 +00:00
Oliver Jowett 9a1b4f3469 Update for the new repository signing setup 2014-12-28 17:53:13 +00:00
Oliver Jowett 9e0800e00a add pbuilder config notes 2014-12-27 22:35:57 +00:00
Oliver Jowett 0fa383f633 Release changelog. 2014-12-27 22:24:51 +00:00
Oliver Jowett 2aa37f06da Link to github from the webmap. 2014-12-27 21:40:18 +00:00
Oliver Jowett 2db9d62c1c Warn if --modeac is used together with --oversample. 2014-12-27 21:25:32 +00:00
Oliver Jowett 727a59e8eb Oversampling is now less scary. 2014-12-27 21:22:43 +00:00
Oliver Jowett 58dfbdcb6b Add support for controlling the accuracy of the receiver location
written in the JSON metadata used by the webmap.
2014-12-27 20:52:56 +00:00
Oliver Jowett bbcfbb8279 Changelog update. 2014-12-27 20:21:36 +00:00
Oliver Jowett 4cc0094781 Remove copies of headers etc that were only needed by Windows builds. 2014-12-27 20:19:05 +00:00
Oliver Jowett 63303b4d07 Remove legacy makefiles / startup scripts that are unused in the Debian package. 2014-12-27 20:17:53 +00:00
Oliver Jowett fc45eded0b Removing COAA/PlanePlotter stuff (+ binary-only object file) that I can't support or test. 2014-12-27 20:16:56 +00:00
Oliver Jowett 6d61d62a66 Pruning windows-related stuff that I can't build/test. 2014-12-27 20:15:08 +00:00
Oliver Jowett 48986c48cc Remove half-implemented --no-decode option. 2014-12-27 20:11:10 +00:00
Oliver Jowett e2153eccde Agh. another typo. 2014-12-27 19:34:24 +00:00
Oliver Jowett 478122e7a3 more docs 2014-12-27 19:29:54 +00:00
Oliver Jowett fbed55dee7 Doc updates. 2014-12-27 19:25:56 +00:00
846 changed files with 52720 additions and 12421 deletions

4
.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
*.xz binary
dsp/generated/* merge=binary linguist-generated
cpu_features/** linguist-vendored
starch/** linguist-vendored

11
.gitignore vendored
View File

@ -7,4 +7,13 @@ frames.js
*~
*.rej
*.orig
untrackedDeveloperSettings.js
untrackedDeveloperSettings.js
view1090
faup1090
package-wheezy
oneoff/convert_benchmark
oneoff/uc8_capture_stats
oneoff/dsp_error_measurement
oneoff/decode_comm_b
starch-benchmark
wisdom.local

31
.travis.yml Normal file
View File

@ -0,0 +1,31 @@
language: c
sudo: required
matrix:
include:
- os: linux
dist: trusty
- os: osx
osx_image: xcode7.3
- os: osx
osx_image: xcode7.1
- os: osx
osx_image: beta-xcode6.2
before_install:
- if [ `uname` = "Linux" ]; then
sudo apt-get update -qq;
sudo apt-get install -y build-essential debhelper librtlsdr-dev libusb-1.0-0-dev pkg-config fakeroot libbladerf-dev dh-systemd;
elif [ `uname` = "Darwin" ]; then
brew update;
brew install -v librtlsdr;
fi
script:
- if [ `uname` = "Linux" ]; then
dpkg-buildpackage -b -us -uc;
elif [ `uname` = "Darwin" ]; then
make;
make test;
fi

339
COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

53
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,53 @@
node(label: 'raspberrypi') {
properties([
pipelineTriggers([
upstream(threshold: 'SUCCESS',
upstreamProjects: "bladeRF/${env.BRANCH_NAME}")
]),
disableConcurrentBuilds(),
durabilityHint(hint: 'PERFORMANCE_OPTIMIZED')
])
def dists = ["bullseye", "buster", "stretch"]
def srcdir = "${WORKSPACE}/src"
stage('Checkout') {
sh "rm -fr ${srcdir}"
sh "mkdir ${srcdir}"
dir(srcdir) {
checkout scm
}
}
for (int i = 0; i < dists.size(); ++i) {
def dist = dists[i]
def pkgdir = "package-${dist}"
def results = "results-${dist}"
stage("Prepare source for ${dist}") {
sh "rm -fr ${pkgdir}"
sh "${srcdir}/prepare-build.sh ${dist} ${pkgdir}"
}
stage("Build for ${dist}") {
sh "rm -fr ${results}"
sh "mkdir -p ${results}"
dir(pkgdir) {
sh "DIST=${dist} BRANCH=${env.BRANCH_NAME} pdebuild --use-pdebuild-internal --debbuildopts -b --buildresult ${WORKSPACE}/${results} -- --override-config"
}
archiveArtifacts artifacts: "${results}/*.deb", fingerprint: true
}
stage("Test install on ${dist}") {
sh "BRANCH=${env.BRANCH_NAME} /build/pi-builder/scripts/validate-packages.sh ${dist} ${results}/dump1090-fa_*.deb"
}
}
stage('Deploy to internal repository') {
for (int i = 0; i < dists.size(); ++i) {
def dist = dists[i]
def results = "results-${dist}"
sh "/build/pi-builder/scripts/deploy.sh -distribution ${dist} -branch ${env.BRANCH_NAME} ${results}/*.deb"
}
}
}

41
LICENSE Normal file
View File

@ -0,0 +1,41 @@
This version of dump1090 is licensed under the GPL, v2 or later.
Please see the individual source files and the file COPYING
for full copyright and license details.
If you need to use dump1090 in a way that is incompatible with
the GPL, please contact Oliver Jowett <oliver@mutability.co.uk>
to discuss your requirements.
The source code incorporates work that was released under a
BSD-style license, reproduced below. For unmodified versions
of the original work that may be used under the terms of that
license, please see https://github.com/antirez/dump1090 and
https://github.com/MalcolmRobb/dump1090.
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

259
Makefile
View File

@ -1,31 +1,250 @@
#
# When building a package or installing otherwise in the system, make
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
#
PROGNAME=dump1090
ifdef PREFIX
BINDIR=$(PREFIX)/bin
SHAREDIR=$(PREFIX)/share/$(PROGNAME)
EXTRACFLAGS=-DHTMLPATH=\"$(SHAREDIR)\"
DUMP1090_VERSION ?= unknown
CFLAGS ?= -O3 -g
DUMP1090_CFLAGS := -std=c11 -fno-common -Wall -Wmissing-declarations -Werror -W
DUMP1090_CPPFLAGS := -I. -D_POSIX_C_SOURCE=200112L -DMODES_DUMP1090_VERSION=\"$(DUMP1090_VERSION)\" -DMODES_DUMP1090_VARIANT=\"dump1090-fa\"
LIBS = -lpthread -lm
SDR_OBJ = cpu.o sdr.o fifo.o sdr_ifile.o dsp/helpers/tables.o
# Try to autodetect available libraries via pkg-config if no explicit setting was used
PKGCONFIG=$(shell pkg-config --version >/dev/null 2>&1 && echo "yes" || echo "no")
ifeq ($(PKGCONFIG), yes)
ifndef RTLSDR
ifdef RTLSDR_PREFIX
RTLSDR := yes
else
RTLSDR := $(shell pkg-config --exists librtlsdr && echo "yes" || echo "no")
endif
endif
ifndef BLADERF
BLADERF := $(shell pkg-config --exists libbladeRF && echo "yes" || echo "no")
endif
ifndef HACKRF
HACKRF := $(shell pkg-config --exists libhackrf && echo "yes" || echo "no")
endif
ifndef LIMESDR
LIMESDR := $(shell pkg-config --exists LimeSuite && echo "yes" || echo "no")
endif
else
# pkg-config not available. Only use explicitly enabled libraries.
RTLSDR ?= no
BLADERF ?= no
HACKRF ?= no
LIMESDR ?= no
endif
CFLAGS+=-O2 -g -Wall -W `pkg-config --cflags librtlsdr`
LIBS=-lpthread -lm -lrt
LIBS_RTL=`pkg-config --libs librtlsdr`
CC=gcc
HOST_UNAME := $(shell uname)
HOST_ARCH := $(shell uname -m)
UNAME ?= $(HOST_UNAME)
ARCH ?= $(HOST_ARCH)
ifeq ($(UNAME), Linux)
DUMP1090_CPPFLAGS += -D_DEFAULT_SOURCE
LIBS += -lrt
LIBS_USB += -lusb-1.0
LIBS_CURSES := -lncurses
CPUFEATURES ?= yes
endif
ifeq ($(UNAME), Darwin)
ifneq ($(shell sw_vers -productVersion | egrep '^10\.([0-9]|1[01])\.'),) # Mac OS X ver <= 10.11
DUMP1090_CPPFLAGS += -DMISSING_GETTIME
COMPAT += compat/clock_gettime/clock_gettime.o
endif
DUMP1090_CPPFLAGS += -DMISSING_NANOSLEEP
COMPAT += compat/clock_nanosleep/clock_nanosleep.o
LIBS_USB += -lusb-1.0
LIBS_CURSES := -lncurses
# cpufeatures reportedly does not work (yet) on darwin arm64
ifneq ($(ARCH),arm64)
CPUFEATURES ?= yes
endif
endif
ifeq ($(UNAME), OpenBSD)
DUMP1090_CPPFLAGS += -DMISSING_NANOSLEEP
COMPAT += compat/clock_nanosleep/clock_nanosleep.o
LIBS_USB += -lusb-1.0
LIBS_CURSES := -lncurses
endif
ifeq ($(UNAME), FreeBSD)
DUMP1090_CPPFLAGS += -D_DEFAULT_SOURCE
LIBS += -lrt
LIBS_USB += -lusb
LIBS_CURSES := -lncurses
endif
ifeq ($(UNAME), NetBSD)
DUMP1090_CPPFLAGS += -D_DEFAULT_SOURCE
LIBS += -lrt
LIBS_USB += -lusb-1.0
LIBS_CURSES := -lcurses
endif
CPUFEATURES ?= no
ifeq ($(CPUFEATURES),yes)
include Makefile.cpufeatures
DUMP1090_CPPFLAGS += -DENABLE_CPUFEATURES -Icpu_features/include
endif
RTLSDR ?= yes
BLADERF ?= yes
ifeq ($(RTLSDR), yes)
SDR_OBJ += sdr_rtlsdr.o
DUMP1090_CPPFLAGS += -DENABLE_RTLSDR
ifdef RTLSDR_PREFIX
DUMP1090_CPPFLAGS += -I$(RTLSDR_PREFIX)/include
ifeq ($(STATIC), yes)
LIBS_SDR += -L$(RTLSDR_PREFIX)/lib -Wl,-Bstatic -lrtlsdr -Wl,-Bdynamic $(LIBS_USB)
else
LIBS_SDR += -L$(RTLSDR_PREFIX)/lib -lrtlsdr $(LIBS_USB)
endif
else
# some packaged .pc files are massively broken, try to handle it
# FreeBSD's librtlsdr.pc includes -std=gnu89 in cflags
# some linux librtlsdr packages return a bare -I/ with no path in --cflags
RTLSDR_CFLAGS := $(shell pkg-config --cflags librtlsdr)
RTLSDR_CFLAGS := $(filter-out -std=%,$(RTLSDR_CFLAGS))
RTLSDR_CFLAGS := $(filter-out -I/,$(RTLSDR_CFLAGS))
DUMP1090_CFLAGS += $(RTLSDR_CFLAGS)
# some linux librtlsdr packages return a bare -L with no path in --libs
# which horribly confuses things because it eats the next option on the command line
RTLSDR_LFLAGS := $(shell pkg-config --libs-only-L librtlsdr)
ifeq ($(RTLSDR_LFLAGS),-L)
LIBS_SDR += $(shell pkg-config --libs-only-l --libs-only-other librtlsdr)
else
LIBS_SDR += $(shell pkg-config --libs librtlsdr)
endif
endif
endif
ifeq ($(BLADERF), yes)
SDR_OBJ += sdr_bladerf.o
DUMP1090_CPPFLAGS += -DENABLE_BLADERF
DUMP1090_CFLAGS += $(shell pkg-config --cflags libbladeRF)
LIBS_SDR += $(shell pkg-config --libs libbladeRF)
endif
ifeq ($(HACKRF), yes)
SDR_OBJ += sdr_hackrf.o
DUMP1090_CPPFLAGS += -DENABLE_HACKRF
DUMP1090_CFLAGS += $(shell pkg-config --cflags libhackrf)
LIBS_SDR += $(shell pkg-config --libs libhackrf)
endif
ifeq ($(LIMESDR), yes)
SDR_OBJ += sdr_limesdr.o
DUMP1090_CPPFLAGS += -DENABLE_LIMESDR
DUMP1090_CFLAGS += $(shell pkg-config --cflags LimeSuite)
LIBS_SDR += $(shell pkg-config --libs LimeSuite)
endif
all: dump1090 view1090
##
## starch (runtime DSP code selection) mix, architecture-specific
##
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRACFLAGS) -c $<
ifneq ($(CPUFEATURES),yes)
# need to be able to detect CPU features at runtime to enable any non-standard compiler flags
STARCH_MIX := generic
DUMP1090_CPPFLAGS += -DSTARCH_MIX_GENERIC
else
ifeq ($(ARCH),x86_64)
# AVX, AVX2
STARCH_MIX := x86
DUMP1090_CPPFLAGS += -DSTARCH_MIX_X86
else ifeq ($(findstring aarch,$(ARCH)),aarch)
STARCH_MIX := aarch64
DUMP1090_CPPFLAGS += -DSTARCH_MIX_AARCH64
else ifeq ($(findstring arm64,$(ARCH)),arm64)
# Apple calls this arm64, not aarch64
STARCH_MIX := aarch64
DUMP1090_CPPFLAGS += -DSTARCH_MIX_AARCH64
else ifeq ($(findstring arm,$(ARCH)),arm)
# ARMv7 NEON
STARCH_MIX := arm
DUMP1090_CPPFLAGS += -DSTARCH_MIX_ARM
else
STARCH_MIX := generic
DUMP1090_CPPFLAGS += -DSTARCH_MIX_GENERIC
endif
endif
all: showconfig dump1090 view1090 starch-benchmark
dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
$(CC) -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LIBS_RTL) $(LDFLAGS)
ALL_CCFLAGS := $(CPPFLAGS) $(DUMP1090_CPPFLAGS) $(CFLAGS) $(DUMP1090_CFLAGS)
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o
$(CC) -g -o view1090 view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o $(LIBS) $(LDFLAGS)
STARCH_COMPILE := $(CC) $(ALL_CCFLAGS) -c
include dsp/generated/makefile.$(STARCH_MIX)
showconfig:
@echo "Building with:" >&2
@echo " Version string: $(DUMP1090_VERSION)" >&2
@echo " Architecture: $(ARCH)" >&2
@echo " DSP mix: $(STARCH_MIX)" >&2
@echo " RTLSDR support: $(RTLSDR)" >&2
@echo " BladeRF support: $(BLADERF)" >&2
@echo " HackRF support: $(HACKRF)" >&2
@echo " LimeSDR support: $(LIMESDR)" >&2
%.o: %.c *.h
$(CC) $(ALL_CCFLAGS) -c $< -o $@
dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o comm_b.o net_io.o crc.o demod_2400.o stats.o cpr.o icao_filter.o track.o util.o convert.o ais_charset.o adaptive.o $(SDR_OBJ) $(COMPAT) $(CPUFEATURES_OBJS) $(STARCH_OBJS)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBS_SDR) $(LIBS_CURSES)
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o comm_b.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o ais_charset.o sdr_stub.o $(COMPAT)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBS_CURSES)
faup1090: faup1090.o anet.o mode_ac.o mode_s.o comm_b.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o ais_charset.o sdr_stub.o $(COMPAT)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS)
starch-benchmark: cpu.o dsp/helpers/tables.o $(CPUFEATURES_OBJS) $(STARCH_OBJS) $(STARCH_BENCHMARK_OBJ)
$(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS)
clean:
rm -f *.o dump1090 view1090
rm -f *.o oneoff/*.o compat/clock_gettime/*.o compat/clock_nanosleep/*.o cpu_features/src/*.o dsp/generated/*.o dsp/helpers/*.o $(CPUFEATURES_OBJS) dump1090 view1090 faup1090 cprtests crctests oneoff/convert_benchmark oneoff/decode_comm_b oneoff/dsp_error_measurement oneoff/uc8_capture_stats starch-benchmark
test: cprtests
./cprtests
cprtests: cpr.o cprtests.o
$(CC) $(ALL_CCFLAGS) -g -o $@ $^ -lm
crctests: crc.c crc.h
$(CC) $(ALL_CCFLAGS) -g -DCRCDEBUG -o $@ $<
benchmarks: oneoff/convert_benchmark
oneoff/convert_benchmark
oneoff/convert_benchmark: oneoff/convert_benchmark.o convert.o util.o dsp/helpers/tables.o cpu.o $(CPUFEATURES_OBJS) $(STARCH_OBJS)
$(CC) $(ALL_CCFLAGS) -g -o $@ $^ -lm -lpthread
oneoff/decode_comm_b: oneoff/decode_comm_b.o comm_b.o ais_charset.o
$(CC) $(ALL_CCFLAGS) -g -o $@ $^ -lm
oneoff/dsp_error_measurement: oneoff/dsp_error_measurement.o dsp/helpers/tables.o cpu.o $(CPUFEATURES_OBJS) $(STARCH_OBJS)
$(CC) $(ALL_CCFLAGS) -g -o $@ $^ -lm
oneoff/uc8_capture_stats: oneoff/uc8_capture_stats.o
$(CC) $(ALL_CCFLAGS) -g -o $@ $^ -lm
starchgen:
dsp/starchgen.py .
.PHONY: wisdom.local
wisdom.local: starch-benchmark
./starch-benchmark -i 5 -o wisdom.local mean_power_u16 mean_power_u16_aligned magnitude_uc8 magnitude_uc8_aligned
./starch-benchmark -i 5 -r wisdom.local -o wisdom.local

38
Makefile.cpufeatures Normal file
View File

@ -0,0 +1,38 @@
# -*- makefile -*-
# cmake integration is a little tricky, so let's do this by hand for now
CPUFEATURES_UNAME ?= $(UNAME)
CPUFEATURES_ARCH ?= $(ARCH)
CPUFEATURES_CFLAGS ?= $(CFLAGS)
CPUFEATURES_OBJS := cpu_features/src/filesystem.o cpu_features/src/stack_line_reader.o cpu_features/src/string_view.o
CPUFEATURES_EXTRA_CFLAGS := -std=c99
CPUFEATURES_EXTRA_CPPFLAGS := -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DNDEBUG -Icpu_features/include
ifeq ($(CPUFEATURES_UNAME),Linux)
CPUFEATURES_OBJS += cpu_features/src/hwcaps.o
CPUFEATURES_EXTRA_CPPFLAGS += -DHAVE_STRONG_GETAUXVAL
endif
ifeq ($(CPUFEATURES_UNAME),Darwin)
CPUFEATURES_EXTRA_CPPFLAGS += -DHAVE_SYSCTLBYNAME
endif
ifeq ($(CPUFEATURES_ARCH),x86_64)
CPUFEATURES_OBJS += cpu_features/src/cpuinfo_x86.o
endif
ifneq (,$(filter i%86,$(CPUFEATURES_ARCH)))
CPUFEATURES_OBJS += cpu_features/src/cpuinfo_x86.o
endif
ifneq (,$(findstring arm,$(CPUFEATURES_ARCH)))
CPUFEATURES_OBJS += cpu_features/src/cpuinfo_arm.o
endif
ifneq (,$(findstring aarch64,$(CPUFEATURES_ARCH)))
CPUFEATURES_OBJS += cpu_features/src/cpuinfo_aarch64.o
endif
$(CPUFEATURES_OBJS): override ALL_CCFLAGS := $(CPUFEATURES_CPPFLAGS) $(CPUFEATURES_EXTRA_CPPFLAGS) $(CPUFEATURES_CFLAGS) $(CPUFEATURES_EXTRA_CFLAGS)

167
README-json.md Normal file
View File

@ -0,0 +1,167 @@
# JSON output formats
dump1090 generates several json files with informaton about the receiver itself, currently known aircraft,
and general statistics. These are used by the webmap, but could also be used by other things
e.g. [this collectd plugin](https://github.com/mutability/dump1090-tools/tree/master/collectd) feeds stats
about dump1090's operation to collectd for later graphing.
## Reading the json files
dump1090-fa writes json files periodically to the location specified by the `--write-json` command line option.
These json files can then be exposed via a separate standalone webserver e.g. lighttpd.
The files are written periodically; for aircraft, typically once a second, for stats, once a minute.
The interval between file updates can be controlled by the `--write-json-every` and `--json-stats-every` options.
As these files are frequently updated, it's a good idea to put them in RAM rather than on disk. Package installs
default to putting the file under `/run`, which is in RAM.
New versions of each file are written to a temporary file, then atomically renamed to the right path, so you should never see partial copies.
Each file contains a single JSON object. The file formats are:
## receiver.json
This file has general metadata about dump1090. It does not change often and you probably just want to read it once at startup.
The keys are:
* version: the version of dump1090 in use
* refresh: how often aircraft.json is updated (for the file version), in milliseconds. the webmap uses this to control its refresh interval.
* history: the current number of valid history files (see below)
* lat: the latitude of the receiver in decimal degrees. Optional, may not be present.
* lon: the longitude of the receiver in decimal degrees. Optional, may not be present.
## aircraft.json
This file contains dump1090's list of recently seen aircraft. The keys are:
* now: the time this file was generated, in seconds since Jan 1 1970 00:00:00 GMT (the Unix epoch).
* messages: the total number of Mode S messages processed since dump1090 started.
* aircraft: an array of JSON objects, one per known aircraft. Each aircraft has the following keys. Keys will be omitted if data is not available.
* hex: the 24-bit ICAO identifier of the aircraft, as 6 hex digits. The identifier may start with '~', this means that the address is a non-ICAO address (e.g. from TIS-B).
* type: type of underlying message, one of:
* adsb_icao: messages from a Mode S or ADS-B transponder, using a 24-bit ICAO address
* adsb_icao_nt: messages from an ADS-B equipped "non-transponder" emitter e.g. a ground vehicle, using a 24-bit ICAO address
* adsr_icao: rebroadcast of ADS-B messages originally sent via another data link e.g. UAT, using a 24-bit ICAO address
* tisb_icao: traffic information about a non-ADS-B target identified by a 24-bit ICAO address, e.g. a Mode S target tracked by secondary radar
* adsb_other: messages from an ADS-B transponder using a non-ICAO address, e.g. anonymized address
* adsr_other: rebroadcast of ADS-B messages originally sent via another data link e.g. UAT, using a non-ICAO address
* tisb_other: traffic information about a non-ADS-B target using a non-ICAO address
* tisb_trackfile: traffic information about a non-ADS-B target using a track/file identifier, typically from primary or Mode A/C radar
* flight: callsign, the flight name or aircraft registration as 8 chars (2.2.8.2.6)
* alt_baro: the aircraft barometric altitude in feet
* alt_geom: geometric (GNSS / INS) altitude in feet referenced to the WGS84 ellipsoid
* gs: ground speed in knots
* ias: indicated air speed in knots
* tas: true air speed in knots
* mach: Mach number
* track: true track over ground in degrees (0-359)
* track_rate: Rate of change of track, degrees/second
* roll: Roll, degrees, negative is left roll
* mag_heading: Heading, degrees clockwise from magnetic north
* true_heading: Heading, degrees clockwise from true north
* baro_rate: Rate of change of barometric altitude, feet/minute
* geom_rate: Rate of change of geometric (GNSS / INS) altitude, feet/minute
* squawk: Mode A code (Squawk), encoded as 4 octal digits
* emergency: ADS-B emergency/priority status, a superset of the 7x00 squawks (2.2.3.2.7.8.1.1)
* category: emitter category to identify particular aircraft or vehicle classes (values A0 - D7) (2.2.3.2.5.2)
* nav_qnh: altimeter setting (QFE or QNH/QNE), hPa
* nav_altitude_mcp: selected altitude from the Mode Control Panel / Flight Control Unit (MCP/FCU) or equivalent equipment
* nav_altitude_fms: selected altitude from the Flight Manaagement System (FMS) (2.2.3.2.7.1.3.3)
* nav_heading: selected heading (True or Magnetic is not defined in DO-260B, mostly Magnetic as that is the de facto standard) (2.2.3.2.7.1.3.7)
* nav_modes: set of engaged automation modes: 'autopilot', 'vnav', 'althold', 'approach', 'lnav', 'tcas'
* lat, lon: the aircraft position in decimal degrees
* nic: Navigation Integrity Category (2.2.3.2.7.2.6)
* rc: Radius of Containment, meters; a measure of position integrity derived from NIC & supplementary bits. (2.2.3.2.7.2.6, Table 2-69)
* seen_pos: how long ago (in seconds before "now") the position was last updated
* version: ADS-B Version Number 0, 1, 2 (3-7 are reserved) (2.2.3.2.7.5)
* nic_baro: Navigation Integrity Category for Barometric Altitude (2.2.5.1.35)
* nac_p: Navigation Accuracy for Position (2.2.5.1.35)
* nac_v: Navigation Accuracy for Velocity (2.2.5.1.19)
* sil: Source Integity Level (2.2.5.1.40)
* sil_type: interpretation of SIL: unknown, perhour, persample
* gva: Geometric Vertical Accuracy (2.2.3.2.7.2.8)
* sda: System Design Assurance (2.2.3.2.7.2.4.6)
* modea: true if we seem to be also receiving Mode A responses from this aircraft
* modec: true if we seem to be also receiving Mode C responses from this aircraft
* mlat: list of fields derived from MLAT data
* tisb: list of fields derived from TIS-B data
* messages: total number of Mode S messages received from this aircraft
* seen: how long ago (in seconds before "now") a message was last received from this aircraft
* rssi: recent average RSSI (signal power), in dbFS; this will always be negative.
Section references (2.2.xyz) refer to DO-260B.
## history_0.json, history_1.json, ..., history_119.json
These files are historical copies of aircraft.json at (by default) 30 second intervals. They follow exactly the
same format as aircraft.json. To know how many are valid, see receiver.json ("history" value). They are written in
a cycle, with history_0 being overwritten after history_119 is generated, so history_0.json is not necessarily the
oldest history entry. To load history, you should:
* read "history" from receiver.json.
* load that many history_N.json files
* sort the resulting files by their "now" values
* process the files in order
## stats.json
This file contains statistics about dump1090's operations.
There are 5 top level keys: "latest", "last1min", "last5min", "last15min", "total". Each key has statistics for a different period, defined by the "start" and "end" subkeys:
* "total" covers the entire period from when dump1090 was started up to the current time
* "last1min" covers a recent 1-minute period. This may be up to 1 minute out of date (i.e. "end" may be up to 1 minute old).
* "last5min" covers a recent 5-minute period. As above, this may be up to 1 minute out of date.
* "last15min" covers a recent 15-minute period. As above, this may be up to 1 minute out of date.
* "latest" covers the time between the end of the "last1min" period and the current time.
Internally, live stats are collected into "latest". Once a minute, "latest" is copied to "last1min" and "latest" is reset. Then "last5min" and "last15min" are recalculated from a history of the last 5 or 15 1-minute periods.
Each period has the following subkeys:
* start: the start time (in seconds-since-1-Jan-1970) of this statistics collection period.
* end: the end time (in seconds-since-1-Jan-1970) of this statistics collection period.
* local: statistics about messages received from a local SDR dongle. Not present in --net-only mode. Has subkeys:
* blocks_processed: number of sample blocks processed
* blocks_dropped: number of sample blocks dropped before processing. A nonzero value means CPU overload.
* modeac: number of Mode A / C messages decoded
* modes: number of Mode S preambles received. This is *not* the number of valid messages!
* bad: number of Mode S preambles that didn't result in a valid message
* unknown_icao: number of Mode S preambles which looked like they might be valid but we didn't recognize the ICAO address and it was one of the message types where we can't be sure it's valid in this case.
* accepted: array. Index N has the number of valid Mode S messages accepted with N-bit errors corrected.
* signal: mean signal power of successfully received messages, in dbFS; always negative.
* peak_signal: peak signal power of a successfully received message, in dbFS; always negative.
* strong_signals: number of messages received that had a signal power above -3dBFS.
* remote: statistics about messages received from remote clients. Only present in --net or --net-only mode. Has subkeys:
* modeac: number of Mode A / C messages received.
* modes: number of Mode S messages received.
* bad: number of Mode S messages that had bad CRC or were otherwise invalid.
* unknown_icao: number of Mode S messages which looked like they might be valid but we didn't recognize the ICAO address and it was one of the message types where we can't be sure it's valid in this case.
* accepted: array. Index N has the number of valid Mode S messages accepted with N-bit errors corrected.
* http_requests: number of HTTP requests handled.
* cpu: statistics about CPU use. Has subkeys:
* demod: milliseconds spent doing demodulation and decoding in response to data from a SDR dongle
* reader: milliseconds spent reading sample data over USB from a SDR dongle
* background: milliseconds spent doing network I/O, processing received network messages, and periodic tasks.
* cpr: statistics about Compact Position Report message decoding. Has subkeys:
* surface: total number of surface CPR messages received
* airborne: total number of airborne CPR messages received
* global_ok: global positions successfuly derived
* global_bad: global positions that were rejected because they were inconsistent
* global_range: global positions that were rejected because they exceeded the receiver max range
* global_speed: global positions that were rejected because they failed the inter-position speed check
* global_skipped: global position attempts skipped because we did not have the right data (e.g. even/odd messages crossed a zone boundary)
* local_ok: local (relative) positions successfully found
* local_aircraft_relative: local positions found relative to a previous aircraft position
* local_receiver_relative: local positions found relative to the receiver position
* local_skipped: local (relative) positions not used because we did not have the right data
* local_range: local positions not used because they exceeded the receiver max range or fell into the ambiguous part of the receiver range
* local_speed: local positions not used because they failed the inter-position speed check
* filtered: number of CPR messages ignored because they matched one of the heuristics for faulty transponder output
* tracks: statistics on aircraft tracks. Each track represents a unique aircraft and persists for up to 5 minutes after the last message
from the aircraft is heard. If messages from the same aircraft are subsequently heard after the 5 minute period, this will be counted
as a new track.
* all: total tracks created
* single_message: tracks consisting of only a single message. These are usually due to message decoding errors that produce a bad aircraft address.
* messages: total number of messages accepted by dump1090 from any source
* messages_by_df: an array of integers where entry N (0..31) is the total number of messages accepted with downlink format (DF) = N.

191
README.adaptive-gain.md Normal file
View File

@ -0,0 +1,191 @@
# Adaptive gain configuration
dump1090-fa can optionally tune the receiver gain automatically to try to
pick a gain value for the particular hardware and RF environment without
manual tuning. This README covers some of the background for why this is
useful, and how to configure dump1090 to enable this feature.
## Background
In general, more receiver gain means better reception. Most ADS-B transmitters
within line of sight transmit with enough power that their messages can
potentially be decoded, but if the receiver gain setting is too low then very
weak signals may still be too weak to be decoded even after amplification.
Adding extra receiver gain helps in this case.
However, there are two problems with just adding more gain to a wideband SDR.
First, _everything_ is amplified, not only the signals of interest. Noise and
RF interference is also amplified. At high gain settings or in noisy RF
environments, this can interfere with receiving the ADS-B signals themselves.
Second, there is a wide range of possible ADS-B signal strengths. There can be
a 60dB or more difference between the weakest signals (a distant aircraft at
the limit of receiver range) and the strongest signals (a nearby aircraft on
the ramp 100m from the receiver). Increasing the receiver gain to handle the
weakest signals can mean that the strongest signals overload the receiver.
A rtlsdr receiver only has about 30-35dB of dynamic range available at a
particular gain setting, so there is no single gain setting that can
simultaneously handle both the weakest and strongest signals.
Adaptive gain tries to deal with these cases by changing the receiver gain
on the fly to handle the signal and noise levels that are currently being seen
without human intervention. It is not perfect and it's not a substitute for
hand-tuning of gain settings, but it aims at picking a reasonable setting for
cases where individual hand-tuning isn't possible.
## Where to configure adaptive gain options
How to configure adaptive gain varies depending on how you have installed
dump1090.
If you are using a PiAware sdcard image, adaptive gain can be configured by
editing `/boot/piaware-config.txt` or by using the `piaware-config` command.
If you are using the Debian package, adaptive gain can be configured by editing
`/etc/default/dump1090-fa`.
If running dump1090 directly, adaptive gain options are set directly by
command-line options.
## Default settings
For new PiAware or Debian package installations, adaptive dynamic range mode
is enabled by default and adaptive burst mode is disabled by default.
For _upgrades_ of PiAware or the Debian package from versions older than 6.0,
both adaptive gain modes are disabled by default.
These defaults can be overridden as described below.
## Adaptive gain in dynamic range mode
The dynamic range adaptive gain mode attempts to set the receiver gain to
maintain a given dynamic range - that is, it tries to set the gain so that
general noise is at or below a given level. This takes into account different
or changing RF environments and different receiver hardware (antenna,
preamplifiers, etc) that affects the overall gain of the system, and usually
will pick a reasonable gain setting without intervention.
To enable this mode:
* Set `adaptive-dynamic-range yes` in piaware-config; or
* Set `ADAPTIVE_DYNAMIC_RANGE=yes` in `/etc/default/dump1090-fa`; or
* Pass the `--adaptive-range` option on the command line.
The default settings for dynamic range will use a dynamic range target chosen
based on SDR type (e.g. 30dB for rtlsdr receivers). This is usually a good
default. To override this target:
* Set `adaptive-dynamic-range-target` in piaware-config; or
* Set `ADAPTIVE_DYNAMIC_RANGE_TARGET` in `/etc/default/dump1090-fa`; or
* Pass the `--adaptive-range-target` option on the command line.
## Adaptive gain in "burst" / loud signal mode
The "burst" adaptive gain mode listens for loud bursts of signal that were
_not_ successfully decoded as ADS-B messages, but which have approximately
the right timing to be possible messages that were lost due to receiver
overloading. When enough overly-loud signals are heard in a short period of
time, dump1090 will _reduce_ the receiver gain to try to allow them to be
received.
This is a more situational setting. It may allow reception of loud nearby
aircraft (e.g. if you are close to an airport). The tradeoff is that when
there are nearby aircraft, overall receiver range may be reduced. Whether
this is a good tradeoff depends on the aircraft you're interested in.
By default, adaptive gain burst mode is disabled.
To enable burst mode:
* Set `adaptive-burst yes` in piaware-config; or
* Set `ADAPTIVE_BURST=yes` in `/etc/default/dump1090-fa`; or
* Pass the `--adaptive-burst` option on the command line.
This mode is more experimental than the dynamic range mode and tweaking of
the advanced burst options may be needed depending on your local installation.
In particular, `--adaptive-burst-loud-rate` and `adaptive-burst-quiet-rate`
may need adjusting. Feedback on what works for you and what doesn't would
be appreciated!
Burst mode and dynamic range mode can be enabled at the same time.
## Limiting the gain range
If you know in advance approximately what the gain setting should be, so
you want to allow adaptive gain to change the gain only within a certain range,
you can set minimum and maximum gain settings in dB. Adaptive gain will only
adjust the gain within this range. To set this:
* Set `adaptive-min-gain` and `adaptive-max-gain` in piaware-config; or
* Set `ADAPTIVE_MIN_GAIN` and `ADAPTIVE_MAX_GAIN` in `/etc/default/dump1090-fa`; or
* Pass the `--adaptive-min-gain` and `--adaptive-max-gain` options on the command line.
If you know approximately where the gain should be, then a good starting point would be
to set the max and min adaptive gain to +/- 10dB around your gain setting.
## Reducing the CPU cost of adaptive gain
The measurements needed to adjust gain have a CPU cost, and on slower
devices it may be useful to reduce the amount of work that adaptive gain does.
This can be done by adjusting the adaptive gain duty cycle. This is a
percentage that controls what fraction of incoming data adaptive gain inspects.
100% means that every sample is inspected. Lower values reduce CPU use, with
a tradeoff that adaptive gain has a less accurate picture of the RF
environment. The default duty cycle is 50% on "fast" CPUs and 10% on "slow"
CPUs (where currently "slow" means "armv6 architecture", for example the
Pi Zero or Pi 1). To reduce the duty cycle further:
* Set `slow-cpu yes` in piaware-config; or
* Set `SLOW_CPU=yes` in `/etc/default/dump1090-fa`; or
* Pass the `--adaptive-duty-cycle` option on the command line
## Advanced options
There are a number of advanced options that are only supported as
command-line options or via the EXTRA_OPTIONS setting in
`/etc/default/dump1090-fa`. They tweak settings that require some knowledge of
dump1090 internals to make sense of, so YMMV.
For a complete list of options, run `dump1090-fa --help` and look at the
adaptive gain section.
## Device support
Currently, adaptive gain is only supported on rtlsdr devices. Support for other
SDRs is planned for the future.
If you're a developer and want to add support for your SDR, you'll need
to implement the gain control API used in `sdr.[ch]`. See `sdr_rtlsdr.c`
(`rtlsdrGetGain`, `rtlsdrSetGain`, etc) for examples.
## Comparison with wiedehopf's auto-gain scripts
There is an [auto-gain script](https://github.com/wiedehopf/adsb-scripts/wiki/Automatic-gain-optimization-for-readsb-and-dump1090-fa)
written by [wiedehopf](https://github.com/wiedehopf) that aims to solve similar
problems. The implementation approaches are quite different, and which one works best
for you will depend on the problem you're trying to solve.
The major differences between adaptive gain and the auto-gain script are:
* Adaptive gain works on short-term data (seconds or minutes) and can react to
changes in a similar timeframe. It tries to set an appropriate gain for the
_current_ environment without much regard for longer-term trends. The auto-gain
script looks at data over longer timeframes (1+ days) and reacts more slowly,
but takes into account data across that whole period.
* Adaptive gain in dynamic range mode looks at an estimate of the noise floor
to decide whether to increase gain. Adaptive gain in burst mode looks at the
signal strength of samples that were _not_ successfully decoded to decide when
to reduce gain. The auto-gain scripts look at the signal strength of _successfully_
decoded messages to decide when to increase or decrease gain. These are each measuring
something different, and which is most effective will depend on the exact RF
environment.
* Adaptive gain burst mode and the auto-gain script superfically measure similar things,
but the difference in measurement timeframe mean they react quite differently. Burst mode
tries to react to transient loud signals i.e. temporarily nearby aircraft. The auto-gain
script uses the loud-messages fraction as an estimate for messages lost to excessive
gain over the long term, not only the transient case.
* Adaptive gain has a few less moving parts (i.e. no external scripts, no config changes over
time) as it's built directly into dump1090 itself.

336
README.md
View File

@ -1,284 +1,122 @@
Dump1090 README
===
# dump1090-fa Debian/Raspbian packages
Dump 1090 is a Mode S decoder specifically designed for RTLSDR devices.
dump1090-fa is a ADS-B, Mode S, and Mode 3A/3C demodulator and decoder that
will receive and decode aircraft transponder messages received via
a directly connected software defined radio, or from data provided over a
network connection.
The main features are:
It is the successor to
[dump1090-mutability](https://github.com/mutability/dump1090) and is
maintained by [FlightAware](http://flightaware.com/).
* Robust decoding of weak messages, with mode1090 many users observed
improved range compared to other popular decoders.
* Network support: TCP30003 stream (MSG5...), Raw packets, HTTP.
* Embedded HTTP server that displays the currently detected aircrafts on
Google Map.
* Single bit errors correction using the 24 bit CRC.
* Ability to decode DF11, DF17 messages.
* Ability to decode DF formats like DF0, DF4, DF5, DF16, DF20 and DF21
where the checksum is xored with the ICAO address by brute forcing the
checksum field using recently seen ICAO addresses.
* Decode raw IQ samples from file (using --ifile command line switch).
* Interactive command-line-interfae mode where aircrafts currently detected
are shown as a list refreshing as more data arrives.
* CPR coordinates decoding and track calculation from velocity.
* TCP server streaming and recceiving raw data to/from connected clients
(using --net).
It can provide a display of locally received aircraft data in a terminal or
via a browser map. Together with [PiAware](http://flightaware.com/adsb/piaware)
it can be used to contribute crowd-sourced flight tracking data to FlightAware.
Installation
---
It is designed to build as a Debian package, but should also be buildable on
many other Linux or Unix-like systems.
Type "make".
## Building under bullseye, buster, or stretch
Normal usage
---
```bash
$ sudo apt-get install build-essential fakeroot debhelper librtlsdr-dev pkg-config libncurses5-dev libbladerf-dev libhackrf-dev liblimesuite-dev
$ ./prepare-build.sh bullseye # or buster, or stretch
$ cd package-bullseye # or buster, or stretch
$ dpkg-buildpackage -b --no-sign
```
To capture traffic directly from your RTL device and show the captured traffic
on standard output, just run the program without options at all:
## Building with limited dependencies
./dump1090
(Supported for bullseye and buster builds only)
To just output hexadecimal messages:
The package supports some build profiles to allow building without all
required SDR libraries being present. This will produce a package with
limited SDR support only.
./dump1090 --raw
Pass `--build-profiles` to `dpkg-buildpackage` with a comma-separated list of
profiles. The list of profiles should include `custom` and zero or more of
`rtlsdr`, `bladerf`, `hackrf`, `limesdr` depending on what you want:
To run the program in interactive mode:
```bash
$ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr # builds with rtlsdr support only
$ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr,bladerf # builds with rtlsdr and bladeRF support
$ dpkg-buildpackage -b --no-sign --build-profiles=custom # builds with _no_ SDR support (network support only)
```
./dump1090 --interactive
## Building manually
To run the program in interactive mode, with networking support, and connect
with your browser to http://localhost:8080 to see live traffic:
You can probably just run "make" after installing the required dependencies.
Binaries are built in the source directory; you will need to arrange to
install them (and a method for starting them) yourself.
./dump1090 --interactive --net
``make BLADERF=no`` will disable bladeRF support and remove the dependency on
libbladeRF.
In iteractive mode it is possible to have a less information dense but more
"arcade style" output, where the screen is refreshed every second displaying
all the recently seen aircrafts with some additional information such as
altitude and flight number, extracted from the received Mode S packets.
``make RTLSDR=no`` will disable rtl-sdr support and remove the dependency on
librtlsdr.
Using files as source of data
---
``make HACKRF=no`` will disable HackRF support and remove the dependency on
libhackrf.
To decode data from file, use:
``make LIMESDR=no`` will disable LimeSDR support and remove the dependency on
libLimeSuite.
./dump1090 --ifile /path/to/binfile
## Building on OSX
The binary file should be created using `rtl_sdr` like this (or with any other
program that is able to output 8-bit unsigned IQ samples at 2Mhz sample rate).
Minimal testing on Mojave 10.14.6, YMMV.
rtl_sdr -f 1090000000 -s 2000000 -g 50 output.bin
```
$ brew install librtlsdr
$ brew install libbladerf
$ brew install hackrf
$ brew install pkg-config
$ make
```
In the example `rtl_sdr` a gain of 50 is used, simply you should use the highest
gain availabe for your tuner. This is not needed when calling Dump1090 itself
as it is able to select the highest gain supported automatically.
## Building on FreeBSD
It is possible to feed the program with data via standard input using
the --ifile option with "-" as argument.
Minimal testing on 12.1-RELEASE, YMMV.
Additional options
---
```
# pkg install gmake
# pkg install pkgconf
# pkg install rtl-sdr
# pkg install bladerf
# pkg install hackrf
$ gmake
```
Dump1090 can be called with other command line options to set a different
gain, frequency, and so forth. For a list of options use:
## Generating wisdom files
./dump1090 --help
dump1090-fa uses [starch](https://github.com/flightaware/starch) to build
multiple versions of the DSP code and choose the fastest supported by the
hardware at runtime. The implementations chosen can been seen by running
`dump1090-fa --version`.
Everything is not documented here should be obvious, and for most users calling
it without arguments at all is the best thing to do.
The implementations used are controlled by "wisdom files", a list of
implementations to use in order of priority. For each DSP function, the first
implementation listed that's supported by the current hardware is used.
By default dump1090-fa provides compiled-in wisdom for [x86](wisdom.x86),
[ARM 32-bit](wisdom.arm), and [ARM 64-bit](wisdom.aarch64). If the defaults
are not suitable for your hardware or if you're building on a different
architecture, you may want to generate your own external wisdom file.
Reliability
---
Ideally, to get stable results, you want to do this on an idle system
with CPU frequency scaling disabled. Running the benchmarks will take
some time (10s of minutes).
By default Dump1090 checks for decoding errors using the 24-bit CRC checksum,
where available. Messages with errors are discarded.
### Package installs
The --fix command line switch enables fixing single bit error correction
based on the CRC checksum. Technically, it uses a table of precomputed
checksum differences resulting from single bit errors to look up the
wrong bit position.
Run `/usr/share/dump1090-fa/generate-wisdom`. Wait.
This is indeed able to fix errors and works reliably in my experience,
however if you are interested in very reliable data I suggest to use
the --no-fix command line switch in order to disable error fixing.
Follow the instructions to copy the resulting wisdom file to `/etc/dump1090-fa/wisdom.local`.
Performances and sensibility of detection
---
Restart dump1090.
In my limited experience Dump1090 was able to decode a big number of messages
even in conditions where I encountered problems using other programs, however
no formal test was performed so I can't really claim that this program is
better or worse compared to other similar programs.
### Manual installs
If you can capture traffic that Dump1090 is not able to decode properly, drop
me an email with a download link. I may try to improve the detection during
my free time (this is just an hobby project).
Run `make wisdom.local`. Wait.
Network server features
---
Copy the resulting `wisdom.local` file somewhere appropriate.
By enabling the networking support with --net Dump1090 starts listening
for clients connections on port 30002 and 30001 (you can change both the
ports if you want, see --help output).
Port 30002
---
Connected clients are served with data ASAP as they arrive from the device
(or from file if --ifile is used) in the raw format similar to the following:
*8D451E8B99019699C00B0A81F36E;
Every entry is separated by a simple newline (LF character, hex 0x0A).
Port 30001
---
Port 30001 is the raw input port, and can be used to feed Dump1090 with
data in the same format as specified above, with hex messages starting with
a `*` and ending with a `;` character.
So for instance if there is another remote Dump1090 instance collecting data
it is possible to sum the output to a local Dump1090 instance doing something
like this:
nc remote-dump1090.example.net 30002 | nc localhost 30001
It is important to note that what is received via port 30001 is also
broadcasted to clients listening to port 30002.
In general everything received from port 30001 is handled exactly like the
normal traffic from RTL devices or from file when --ifile is used.
It is possible to use Dump1090 just as an hub using --ifile with /dev/zero
as argument as in the following example:
./dump1090 --net-only
Or alternatively to see what's happening on the screen:
./dump1090 --net-only --interactive
Then you can feed it from different data sources from the internet.
Port 30003
---
Connected clients are served with messages in SBS1 (BaseStation) format,
similar to:
MSG,4,,,738065,,,,,,,,420,179,,,0,,0,0,0,0
MSG,3,,,738065,,,,,,,35000,,,34.81609,34.07810,,,0,0,0,0
This can be used to feed data to various sharing sites without the need to use another decoder.
Antenna
---
Mode S messages are transmitted in the 1090 Mhz frequency. If you have a decent
antenna you'll be able to pick up signals from aircrafts pretty far from your
position, especially if you are outdoor and in a position with a good sky view.
You can easily build a very cheap antenna following the istructions at:
http://antirez.com/news/46
With this trivial antenna I was able to pick up signals of aircrafts 200+ Km
away from me.
If you are interested in a more serious antenna check the following
resources:
* http://gnuradio.org/redmine/attachments/download/246/06-foster-adsb.pdf
* http://www.lll.lu/~edward/edward/adsb/antenna/ADSBantenna.html
* http://modesbeast.com/pix/adsb-ant-drawing.gif
Aggressive mode
---
With --aggressive it is possible to activate the *aggressive mode* that is a
modified version of the Mode S packet detection and decoding.
The aggresive mode uses more CPU usually (especially if there are many planes
sending DF17 packets), but can detect a few more messages.
The algorithm in aggressive mode is modified in the following ways:
* Up to two demodulation errors are tolerated (adjacent entires in the
magnitude vector with the same eight). Normally only messages without
errors are checked.
* It tries to fix DF17 messages with CRC errors resulting from any two bit
errors.
The use of aggressive mdoe is only advised in places where there is
low traffic in order to have a chance to capture some more messages.
Debug mode
---
The Debug mode is a visual help to improve the detection algorithm or to
understand why the program is not working for a given input.
In this mode messages are displayed in an ASCII-art style graphical
representation, where the individial magnitude bars sampled at 2Mhz are
displayed.
An index shows the sample number, where 0 is the sample where the first
Mode S peak was found. Some additional background noise is also added
before the first peak to provide some context.
To enable debug mode and check what combinations of packets you can
log, use `mode1090 --help` to obtain a list of available debug flags.
Debug mode includes an optional javascript output that is used to visualize
packets using a web browser, you can use the file debug.html under the
'tools' directory to load the generated frames.js file.
How this program works?
---
The code is very documented and written in order to be easy to understand.
For the diligent programmer with a Mode S specification on his hands it
should be trivial to understand how it works.
The algorithms I used were obtained basically looking at many messages
as displayed using a trow-away SDL program, and trying to model the algorithm
based on how the messages look graphically.
How to test the program?
---
If you have an RTLSDR device and you happen to be in an area where there
are aircrafts flying over your head, just run the program and check for signals.
However if you don't have an RTLSDR device, or if in your area the presence
of aircrafts is very limited, you may want to try the sample file distributed
with the Dump1090 distribution under the "testfiles" directory.
Just run it like this:
./dump1090 --ifile testfiles/modes1.bin
What is --strip mode?
---
It is just a simple filter that will get raw IQ 8 bit samples in input
and will output a file missing all the parts of the file where I and Q
are lower than the specified <level> for more than 32 samples.
Use it like this:
cat big.bin | ./dump1090 --snip 25 > small.bin
I used it in order to create a small test file to include inside this
program source code distribution.
Contributing
---
Dump1090 was written during some free time during xmas 2012, it is an hobby
project so I'll be able to address issues and improve it only during
free time, however you are incouraged to send pull requests in order to
improve the program. A good starting point can be the TODO list included in
the source distribution.
Credits
---
Dump1090 was written by Salvatore Sanfilippo <antirez@gmail.com> and is
released under the BSD three clause license.
Update the dump1090-fa command-line options to include `--wisdom /path/to/wisdom.local`

5
TODO
View File

@ -1,5 +0,0 @@
TODO
* Extract more information from captured Mode S messages.
* Improve the web interface gmap.html.
* Enhance the algorithm to reliably decode more messages.

645
adaptive.c Normal file
View File

@ -0,0 +1,645 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// adaptive.c: adaptive gain control
//
// Copyright (c) 2021 FlightAware, LLC
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dump1090.h"
#include "adaptive.h"
//
// gain limits
//
static int adaptive_gain_min;
static int adaptive_gain_max;
// gain steps relative to current gain
static float adaptive_gain_up_db;
static float adaptive_gain_down_db;
//
// block handling
//
// 1 block = approx 1 second of samples. Control updates are done at the end of each block only.
// Each block is made up of an integer number of subblocks (currently 20)
//
// 1 subblock = approx 50ms of samples. Duty cycle decisions are made at the subblock level;
// either the whole subblock is processed, or the whole subblock is skipped.
// Each subblock is made up of an integer number of windows (currently 1250)
//
// 1 window = approx 40us of samples. Burst measurements are made by counting samples within each window.
//
// All three levels are aligned, i.e. every block boundary is also a subblock boundary;
// every subblock boundary is also a window boundary.
static const unsigned adaptive_subblocks_per_block = 20; // subblocks per block
static unsigned adaptive_subblocks_remaining; // subblocks remaining in the current block
// Duty cycle is expressed as N/D
// where N = adaptive_subblbock_dutycycle_N = adaptive_subblocks_per_block * Modes.adaptive_duty_cycle
// and D = adaptive_subblocks_dutycycle_D = adaptive_subblocks_per_block
//
// i.e. within each block, there are exactly N active subblocks out of D total subblocks
//
// The active subblocks are distributed evenly across the block by increasing a counter by N on each
// subblock, modulo D, and marking the subblock as active each time the counter rolls over.
static unsigned adaptive_subblock_dutycycle_N; // subblock duty cycle numerator N
// stretch gcc doesn't like this as a separate const
#define adaptive_subblock_dutycycle_D adaptive_subblocks_per_block
static unsigned adaptive_subblock_dutycycle_counter; // subblock duty cycle counter (modulo D)
static bool adaptive_subblock_active; // is the current subblock active i.e. samples should be processed, not skipped?
static unsigned adaptive_samples_per_subblock; // samples per subblock
static unsigned adaptive_subblock_samples_remaining; // samples remaining in the current subblock
static unsigned adaptive_samples_per_window; // samples per window
void adaptive_init();
void adaptive_update(uint16_t *buf, unsigned length, struct modesMessage *decoded);
static void adaptive_update_subblock(uint16_t *buf, unsigned length, struct modesMessage *decoded);
static void adaptive_end_of_block();
static void adaptive_control_update();
//
// burst handling
//
static unsigned adaptive_burst_window_remaining; // samples remaining in the current burst window
static unsigned adaptive_burst_window_counter; // loud samples seen in current burst window
static unsigned adaptive_burst_runlength; // consecutive loud burst windows seen
static unsigned adaptive_burst_block_loud_undecoded; // loud undecoded bursts seen in this block so far
static unsigned adaptive_burst_block_loud_decoded; // loud decoded messages seen in this block so far
static double adaptive_burst_loud_undecoded_smoothed; // smoothed rate of loud misdecodes per block
static double adaptive_burst_loud_decoded_smoothed; // smoothed rate of loud successful decodes per block
static unsigned adaptive_burst_change_timer; // countdown inhibiting control after changing gain
static double adaptive_burst_loud_threshold; // current signal level threshold for a "loud decode"
static unsigned adaptive_burst_loud_blocks = 0; // consecutive blocks with loud rate
static unsigned adaptive_burst_quiet_blocks = 0; // consecutive blocks with quiet rate
static void adaptive_burst_update(uint16_t *buf, unsigned length);
static void adaptive_burst_skip(unsigned length);
static unsigned adaptive_burst_count_samples(uint16_t *buf, unsigned n);
static void adaptive_burst_scan_windows(uint16_t *buf, unsigned windows);
static void adaptive_burst_end_of_window(unsigned counter);
static void adaptive_burst_end_of_block();
//
// noise floor measurement (adaptive dynamic range)
//
static unsigned *adaptive_range_radix; // radix-sort buckets for current block
static unsigned adaptive_range_radix_counter; // sum of all radix-sort buckets (= number of samples sorted)
static double adaptive_range_smoothed; // smoothed noise floor estimate, dBFS
static enum { RANGE_SCAN_IDLE, RANGE_SCAN_UP, RANGE_SCAN_DOWN, RANGE_RESCAN_UP, RANGE_RESCAN_DOWN } adaptive_range_state = RANGE_SCAN_UP;
static unsigned adaptive_range_change_timer; // countdown inhibiting control after changing gain
static unsigned adaptive_range_rescan_timer; // countdown to next upwards gain reprobe
static int adaptive_range_gain_limit; // probed maximum gain step with acceptable dynamic range
static void adaptive_range_update(uint16_t *buf, unsigned length);
static void adaptive_range_end_of_block();
// Try to change the SDR gain to 'step' and tell the user about it,
// with 'why' as the reason to show. Return true if the gain actually changed.
static bool adaptive_set_gain(int step, const char *why)
{
if (step < adaptive_gain_min)
step = adaptive_gain_min;
if (step > adaptive_gain_max)
step = adaptive_gain_max;
int current_gain = sdrGetGain();
if (current_gain == step)
return false;
fprintf(stderr, "adaptive: changing gain from %.1fdB (step %d) to %.1fdB (step %d) because: %s\n",
sdrGetGainDb(current_gain), current_gain, sdrGetGainDb(step), step, why);
int new_gain = sdrSetGain(step);
bool changed = (current_gain != new_gain);
if (changed)
++Modes.stats_current.adaptive_gain_changes;
return changed;
}
// Update internal state to reflect a gain change
// (usually after adaptive_set_gain returns true, but also called during init)
static void adaptive_gain_changed()
{
int new_gain = sdrGetGain();
adaptive_gain_up_db = sdrGetGainDb(new_gain + 1) - sdrGetGainDb(new_gain);
adaptive_gain_down_db = sdrGetGainDb(new_gain) - sdrGetGainDb(new_gain - 1);
double loud_threshold_dbfs = 0 - adaptive_gain_up_db - 3.0;
adaptive_burst_loud_threshold = pow(10, loud_threshold_dbfs / 10.0);
adaptive_range_change_timer = Modes.adaptive_range_change_delay;
adaptive_burst_change_timer = Modes.adaptive_burst_change_delay;
adaptive_burst_loud_blocks = 0;
adaptive_burst_quiet_blocks = 0;
}
// External init entry point
void adaptive_init()
{
int maxgain = sdrGetMaxGain();
// If the SDR doesn't support gain control, disable ourselves
if (maxgain < 0) {
if (Modes.adaptive_burst_control || Modes.adaptive_range_control) {
fprintf(stderr, "warning: adaptive gain control requested, but SDR gain control not available, ignored.\n");
}
Modes.adaptive_burst_control = false;
Modes.adaptive_range_control = false;
}
// If we're disabled, do nothing
if (!Modes.adaptive_burst_control && !Modes.adaptive_range_control)
return;
// Set up window, subblock, and block sizes
// Look for 40us bursts
adaptive_samples_per_window = Modes.sample_rate / 25000;
// Use ~50ms subblocks; ensure it's an exact multiple of window size
adaptive_samples_per_subblock = adaptive_samples_per_window * 1250;
adaptive_subblocks_remaining = adaptive_subblocks_per_block;
adaptive_subblock_samples_remaining = adaptive_samples_per_subblock;
adaptive_subblock_active = false;
float N = roundf(adaptive_subblock_dutycycle_D * Modes.adaptive_duty_cycle);
if (N <= 0)
N = 1;
if (N > adaptive_subblock_dutycycle_D)
N = adaptive_subblock_dutycycle_D;
fprintf(stderr, "adaptive: using %.0f%% duty cycle\n", 100.0 * N / adaptive_subblock_dutycycle_D);
adaptive_subblock_dutycycle_N = (unsigned)N;
adaptive_burst_window_remaining = adaptive_samples_per_window;
adaptive_burst_window_counter = 0;
adaptive_range_radix = calloc(sizeof(unsigned), 65536);
adaptive_range_state = RANGE_RESCAN_UP;
// select and enforce gain limits
for (adaptive_gain_min = 0; adaptive_gain_min < maxgain; ++adaptive_gain_min) {
if (sdrGetGainDb(adaptive_gain_min) >= Modes.adaptive_min_gain_db)
break;
}
for (adaptive_gain_max = maxgain; adaptive_gain_max > adaptive_gain_min; --adaptive_gain_max) {
if (sdrGetGainDb(adaptive_gain_max) <= Modes.adaptive_max_gain_db)
break;
}
fprintf(stderr, "adaptive: enabled adaptive gain control with gain limits %.1fdB (step %d) .. %.1fdB (step %d)\n",
sdrGetGainDb(adaptive_gain_min), adaptive_gain_min, sdrGetGainDb(adaptive_gain_max), adaptive_gain_max);
if (Modes.adaptive_range_control)
fprintf(stderr, "adaptive: enabled dynamic range control, target dynamic range %.1fdB\n", Modes.adaptive_range_target);
if (Modes.adaptive_burst_control)
fprintf(stderr, "adaptive: enabled burst control\n");
adaptive_set_gain(sdrGetGain(), "constraining gain to adaptive gain limits");
adaptive_gain_changed();
adaptive_range_gain_limit = sdrGetGain();
}
// Feed some samples into the adaptive system. Any number of samples might be passed in.
void adaptive_update(uint16_t *buf, unsigned length, struct modesMessage *decoded)
{
if (!Modes.adaptive_burst_control && !Modes.adaptive_range_control)
return;
// process complete subblocks
while (length >= adaptive_subblock_samples_remaining) {
if (adaptive_subblock_active)
adaptive_update_subblock(buf, adaptive_subblock_samples_remaining, decoded);
buf += adaptive_subblock_samples_remaining;
length -= adaptive_subblock_samples_remaining;
adaptive_subblock_samples_remaining = adaptive_samples_per_subblock;
adaptive_subblock_dutycycle_counter += adaptive_subblock_dutycycle_N;
if (adaptive_subblock_dutycycle_counter >= adaptive_subblock_dutycycle_D) {
adaptive_subblock_dutycycle_counter -= adaptive_subblock_dutycycle_D;
adaptive_subblock_active = true;
} else {
adaptive_subblock_active = false;
// fake a quiet window to reset any existing run
adaptive_burst_end_of_window(0);
}
if (!--adaptive_subblocks_remaining) {
// Block completed, do a control update
adaptive_subblocks_remaining = adaptive_subblocks_per_block;
adaptive_end_of_block();
}
}
// process final samples that don't complete a subblock
if (length > 0) {
if (adaptive_subblock_active)
adaptive_update_subblock(buf, length, decoded);
adaptive_subblock_samples_remaining -= length;
}
}
// Feed some samples into the adaptive system. The samples are guaranteed to not cross a subblock boundary.
// The samples should be processsed (i.e. duty cycle is in the active part)
static void adaptive_update_subblock(uint16_t *buf, unsigned length, struct modesMessage *decoded)
{
if (decoded) {
if (/* decoded->msgbits == 112 && */ decoded->signalLevel >= adaptive_burst_loud_threshold)
++adaptive_burst_block_loud_decoded;
adaptive_burst_skip(length);
} else {
adaptive_burst_update(buf, length);
adaptive_range_update(buf, length);
}
}
// Burst measurement: ignore the next 'length' samples (they are a successfully decoded message)
static void adaptive_burst_skip(unsigned length)
{
if (!Modes.adaptive_burst_control)
return;
// first window
if (length < adaptive_burst_window_remaining) {
// partial fill
adaptive_burst_window_remaining -= length;
return;
}
// skip remainder of first window, dispatch it
adaptive_burst_end_of_window(adaptive_burst_window_counter);
length -= adaptive_burst_window_remaining;
// skip remaining windows, dispatch them
unsigned windows = length / adaptive_samples_per_window;
unsigned samples = windows * adaptive_samples_per_window;
while (windows--)
adaptive_burst_end_of_window(0);
length -= samples;
// final partial window
adaptive_burst_window_counter = 0;
adaptive_burst_window_remaining = adaptive_samples_per_window - length;
}
// Burst measurement: process 'length' samples from 'buf', look for loud bursts;
// the samples might cross burst window boundaries;
// the samples will not cross a block boundary.
static void adaptive_burst_update(uint16_t *buf, unsigned length)
{
if (!Modes.adaptive_burst_control)
return;
// first window
if (length < adaptive_burst_window_remaining) {
// partial fill
adaptive_burst_window_counter += adaptive_burst_count_samples(buf, length);
adaptive_burst_window_remaining -= length;
return;
}
// complete fill of first partial window
unsigned n = adaptive_burst_window_remaining;
unsigned counter = adaptive_burst_window_counter + adaptive_burst_count_samples(buf, n);
adaptive_burst_end_of_window(counter);
buf += n;
length -= n;
// remaining windows
unsigned windows = length / adaptive_samples_per_window;
unsigned samples = windows * adaptive_samples_per_window;
adaptive_burst_scan_windows(buf, windows);
buf += samples;
length -= samples;
// final partial window
adaptive_burst_window_counter = adaptive_burst_count_samples(buf, length);
adaptive_burst_window_remaining = adaptive_samples_per_window - length;
}
// Burst measurement: process 'windows' complete burst windows starting at 'buf';
// 'buf' is aligned to the start of a burst window
static void adaptive_burst_scan_windows(uint16_t *buf, unsigned windows)
{
while (windows--) {
unsigned counter = adaptive_burst_count_samples(buf, adaptive_samples_per_window);
buf += adaptive_samples_per_window;
adaptive_burst_end_of_window(counter);
}
}
// Burst measurement: process 'n' samples from 'buf', look for loud samples;
// the samples are guaranteed not to cross window boundaries;
// return the number of loud samples seen
static inline unsigned adaptive_burst_count_samples(uint16_t *buf, unsigned n)
{
unsigned counter;
starch_count_above_u16(buf, n, 46395 /* -3dBFS */, &counter);
return counter;
}
// Burst measurement: we reached the end of a burst window with 'counter'
// loud samples seen, handle that window.
static void adaptive_burst_end_of_window(unsigned counter)
{
if (counter > adaptive_samples_per_window / 4) {
// This window is loud, extend any existing run of loud windows
++adaptive_burst_runlength;
} else {
// Quiet window. If we saw a run of loud windows >= 80us long, count
// that as a candidate for an over-amplified message that was
// not decoded.
if (adaptive_burst_runlength >= 2 && adaptive_burst_runlength <= 5)
++adaptive_burst_block_loud_undecoded;
adaptive_burst_runlength = 0;
}
}
// Noise measurement: process 'length' samples from 'buf'.
// The samples will not cross a block boundary.
static void adaptive_range_update(uint16_t *buf, unsigned length)
{
if (!Modes.adaptive_range_control)
return;
adaptive_range_radix_counter += length;
while (length--) {
// do a very simple radix sort of sample magnitudes
// so we can later find the Nth percentile value
++adaptive_range_radix[buf[0]];
++buf;
}
}
// Noise measurement: we reached the end of a block, update
// our noise estimate
static void adaptive_range_end_of_block()
{
if (!Modes.adaptive_range_control)
return;
unsigned n = 0, i = 0;
// measure Nth percentile magnitude
unsigned count_n = adaptive_range_radix_counter * Modes.adaptive_range_percentile / 100;
while (i < 65536 && n <= count_n)
n += adaptive_range_radix[i++];
uint16_t percentile_n = i - 1;
// maintain an EMA of the Nth percentile
adaptive_range_smoothed = adaptive_range_smoothed * (1 - Modes.adaptive_range_alpha) + percentile_n * Modes.adaptive_range_alpha;
// .. report to stats in dBFS
if (adaptive_range_smoothed > 0) {
Modes.stats_current.adaptive_noise_dbfs = 20 * log10(adaptive_range_smoothed / 65536.0);
} else {
Modes.stats_current.adaptive_noise_dbfs = 0;
}
// reset radix sort for the next block
memset(adaptive_range_radix, 0, 65536 * sizeof(unsigned));
adaptive_range_radix_counter = 0;
}
// Burst measurement: we reached the end of a block, update our burst rate estimate
static void adaptive_burst_end_of_block()
{
if (!Modes.adaptive_burst_control)
return;
// scale rates based on the actual duty cycle fraction
// (e.g. if we are only inspecting 2/5 of samples, then scale the rate by 5/2)
double scale = (double)adaptive_subblock_dutycycle_D / adaptive_subblock_dutycycle_N;
// maintain an EMA of the number of undecoded loud bursts seen per block
Modes.stats_current.adaptive_loud_undecoded += adaptive_burst_block_loud_undecoded;
adaptive_burst_loud_undecoded_smoothed = adaptive_burst_loud_undecoded_smoothed * (1 - Modes.adaptive_burst_alpha) + scale * adaptive_burst_block_loud_undecoded * Modes.adaptive_burst_alpha;
adaptive_burst_block_loud_undecoded = 0;
// maintain an EMA of the number of decoded, but loud, messages seen per block
Modes.stats_current.adaptive_loud_decoded += adaptive_burst_block_loud_decoded;
adaptive_burst_loud_decoded_smoothed = adaptive_burst_loud_decoded_smoothed * (1 - Modes.adaptive_burst_alpha) + scale * adaptive_burst_block_loud_decoded * Modes.adaptive_burst_alpha;
adaptive_burst_block_loud_decoded = 0;
}
void flush_stats(uint64_t now);
static void adaptive_increase_gain(const char *why)
{
if (adaptive_set_gain(sdrGetGain() + 1, why))
adaptive_gain_changed();
}
static void adaptive_decrease_gain(const char *why)
{
if (adaptive_set_gain(sdrGetGain() - 1, why))
adaptive_gain_changed();
}
// Adaptive gain: we reached a block boundary. Update measurements and act on them.
static void adaptive_end_of_block()
{
adaptive_range_end_of_block();
adaptive_burst_end_of_block();
adaptive_control_update();
Modes.stats_current.adaptive_valid = true;
unsigned current = Modes.stats_current.adaptive_gain = sdrGetGain();
Modes.stats_current.adaptive_range_gain_limit = adaptive_range_gain_limit;
++Modes.stats_current.adaptive_gain_seconds[current < STATS_GAIN_COUNT ? current : STATS_GAIN_COUNT-1];
}
static void adaptive_control_update()
{
// votes for what to do with the gain
// "gain_not_up" overlaps somewhat with "gain_down", but they are not identical;
// burst control may want to prevent gain from increasing, but not necessarily
// decrease gain.
bool gain_up = false;
const char *gain_up_reason = NULL;
bool gain_down = false;
const char *gain_down_reason = NULL;
bool gain_not_up = false;
int current_gain = sdrGetGain();
if (adaptive_burst_change_timer)
--adaptive_burst_change_timer;
if (adaptive_range_change_timer > 0)
--adaptive_range_change_timer;
if (adaptive_range_rescan_timer > 0)
--adaptive_range_rescan_timer;
if (Modes.adaptive_burst_control && !adaptive_burst_change_timer) {
if (adaptive_burst_loud_undecoded_smoothed > Modes.adaptive_burst_loud_rate) {
adaptive_burst_quiet_blocks = 0;
++adaptive_burst_loud_blocks;
} else if (adaptive_burst_loud_decoded_smoothed < Modes.adaptive_burst_quiet_rate) {
adaptive_burst_loud_blocks = 0;
++adaptive_burst_quiet_blocks;
} else {
adaptive_burst_loud_blocks = 0;
adaptive_burst_quiet_blocks = 0;
}
if (adaptive_burst_loud_blocks >= Modes.adaptive_burst_loud_runlength) {
// we need to reduce gain (further)
gain_down = gain_not_up = true;
gain_down_reason = "high rate of loud undecoded messages";
// if we're currently doing a downward scan, reducing gain further may confuse it;
// stop that scan and restart it once we are no longer in a reduced-gain state
if (adaptive_range_state == RANGE_SCAN_DOWN || adaptive_range_state == RANGE_RESCAN_DOWN) {
adaptive_range_state = RANGE_SCAN_IDLE;
adaptive_range_rescan_timer = 0;
}
} else if (adaptive_burst_quiet_blocks < Modes.adaptive_burst_quiet_runlength) {
// we're OK at the current gain, but should not increase it
gain_not_up = true;
} else if (current_gain < adaptive_range_gain_limit) {
// we're OK at the current gain, and can increase gain to the previously discovered
// dynamic range limit
gain_up = true;
gain_up_reason = "low loud message rate and gain below dynamic range limit";
}
}
if (Modes.adaptive_range_control && !adaptive_range_change_timer) {
float available_range = -20 * log10(adaptive_range_smoothed / 65536.0);
// allow the gain limit to increase if this gain setting is acceptable
// (decreasing the limit is done separately depending on the current state as we make slightly different decisions in IDLE
// to provide hysteresis)
if (available_range >= Modes.adaptive_range_target && current_gain > adaptive_range_gain_limit) {
adaptive_range_gain_limit = current_gain;
}
switch (adaptive_range_state) {
case RANGE_SCAN_UP:
case RANGE_RESCAN_UP:
if (available_range < Modes.adaptive_range_target) {
// Current gain fails to meet our target. Switch to downward scanning.
fprintf(stderr, "adaptive: available dynamic range (%.1fdB) < required dynamic range (%.1fdB), switching to downward scan\n", available_range, Modes.adaptive_range_target);
gain_down = gain_not_up = true;
gain_down_reason = "probing dynamic range gain lower bound";
adaptive_range_state = (adaptive_range_state == RANGE_RESCAN_UP ? RANGE_RESCAN_DOWN : RANGE_SCAN_DOWN);
if (adaptive_range_gain_limit >= current_gain) {
adaptive_range_gain_limit = current_gain - 1;
}
break;
}
if (sdrGetGain() >= adaptive_gain_max) {
// We have reached our upper gain limit
fprintf(stderr, "adaptive: reached upper gain limit, halting dynamic range scan here\n");
adaptive_range_state = RANGE_SCAN_IDLE;
adaptive_range_rescan_timer = Modes.adaptive_range_rescan_delay;
break;
}
// This gain step is OK and we have more to try, try the next gain step up.
// (But if burst detection has inhibited increasing gain, don't do anything yet, just try again next block)
if (!gain_not_up) {
fprintf(stderr, "adaptive: available dynamic range (%.1fdB) >= required dynamic range (%.1fdB), continuing upward scan\n", available_range, Modes.adaptive_range_target);
gain_up = true;
gain_up_reason = "probing dynamic range gain upper bound";
}
break;
case RANGE_SCAN_DOWN:
case RANGE_RESCAN_DOWN:
if (available_range >= Modes.adaptive_range_target) {
// Current gain meets our target; we are done with the scan.
fprintf(stderr, "adaptive: available dynamic range (%.1fdB) >= required dynamic range (%.1fdB), stopping downwards scan here\n", available_range, Modes.adaptive_range_target);
adaptive_range_state = RANGE_SCAN_IDLE;
adaptive_range_rescan_timer = (adaptive_range_state == RANGE_SCAN_DOWN ? Modes.adaptive_range_scan_delay : Modes.adaptive_range_rescan_delay);
break;
}
if (adaptive_range_gain_limit >= current_gain) {
adaptive_range_gain_limit = current_gain - 1;
}
if (sdrGetGain() <= adaptive_gain_min) {
fprintf(stderr, "adaptive: reached lower gain limit, halting dynamic range scan here\n");
adaptive_range_state = RANGE_SCAN_IDLE;
adaptive_range_rescan_timer = Modes.adaptive_range_rescan_delay;
break;
}
// This gain step is too loud and we have more to try, try the next gain step down
fprintf(stderr, "adaptive: available dynamic range (%.1fdB) < required dynamic range (%.1fdB), continuing downwards scan\n", available_range, Modes.adaptive_range_target);
gain_down = gain_not_up = true;
gain_down_reason = "probing dynamic range gain lower bound";
break;
case RANGE_SCAN_IDLE:
// Look for increased noise that could be compensated for by decreasing gain.
// Do this even if we're waiting to rescan or if burst control is also active
if (available_range + adaptive_gain_down_db / 2 < Modes.adaptive_range_target && sdrGetGain() > adaptive_gain_min) {
fprintf(stderr, "adaptive: available dynamic range (%.1fdB) + half gain step down (%.1fdB) < required dynamic range (%.1fdB), starting downward scan\n",
available_range, Modes.adaptive_range_target, adaptive_gain_down_db);
if (adaptive_range_gain_limit >= current_gain) {
adaptive_range_gain_limit = current_gain - 1;
}
adaptive_range_state = RANGE_SCAN_DOWN;
gain_down = gain_not_up = true;
gain_down_reason = "dynamic range fell below target value";
break;
}
// Infrequently consider increasing gain to handle the case where we've selected a too-low gain where the noise floor is dominated by noise unrelated to the gain setting.
// But don't do this while burst control is preventing gain increases.
if (!adaptive_range_rescan_timer && !gain_not_up) {
if (available_range >= Modes.adaptive_range_target && sdrGetGain() < adaptive_gain_max) {
fprintf(stderr, "adaptive: start periodic scan for acceptable dynamic range at increased gain\n");
gain_up = true;
gain_up_reason = "periodic re-probing of dynamic range gain upper bound";
adaptive_range_state = RANGE_RESCAN_UP;
break;
}
// Nothing to do for a while.
adaptive_range_rescan_timer = Modes.adaptive_range_rescan_delay;
}
break;
default:
fprintf(stderr, "adaptive: in a weird state (%d), trying to fix it\n", adaptive_range_state);
adaptive_range_state = RANGE_SCAN_IDLE;
adaptive_range_rescan_timer = Modes.adaptive_range_rescan_delay;
break;
}
}
// now actually perform any gain changes
if (gain_down)
adaptive_decrease_gain(gain_down_reason);
else if (gain_up && !gain_not_up)
adaptive_increase_gain(gain_up_reason);
}

30
adaptive.h Normal file
View File

@ -0,0 +1,30 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// adaptive.h: adaptive gain control prototypes
//
// Copyright (c) 2021 FlightAware, LLC
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef ADAPTIVE_H
#define ADAPTIVE_H
#include <inttypes.h>
struct modesMessage;
void adaptive_init();
void adaptive_update(uint16_t *buf, unsigned length, struct modesMessage *decoded);
#endif

3
ais_charset.c Normal file
View File

@ -0,0 +1,3 @@
#include "ais_charset.h"
char ais_charset[64] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?";

6
ais_charset.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef AIS_CHARSET_H
#define AIS_CHARSET_H
extern char ais_charset[64];
#endif

261
anet.c
View File

@ -1,3 +1,26 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// anet.c: Basic TCP socket stuff made a bit less boring
//
// Copyright (c) 2016 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file incorporates work covered by the following copyright and
// permission notice:
//
/* anet.c -- Basic TCP socket stuff made a bit less boring
*
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
@ -28,25 +51,20 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#else
#include "winstubs.h" //Put everything Windows specific in here
#include "dump1090.h"
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include "anet.h"
@ -63,7 +81,7 @@ static void anetSetError(char *err, const char *fmt, ...)
int anetNonBlock(char *err, int fd)
{
int flags;
#ifndef _WIN32
/* Set the socket nonblocking.
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. */
@ -75,14 +93,7 @@ int anetNonBlock(char *err, int fd)
anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno));
return ANET_ERR;
}
#else
flags = 1;
if (ioctlsocket(fd, FIONBIO, &flags)) {
errno = WSAGetLastError();
anetSetError(err, "ioctlsocket(FIONBIO): %s", strerror(errno));
return ANET_ERR;
}
#endif
return ANET_OK;
}
@ -117,31 +128,10 @@ int anetTcpKeepAlive(char *err, int fd)
return ANET_OK;
}
int anetResolve(char *err, char *host, char *ipbuf)
static int anetCreateSocket(char *err, int domain)
{
struct sockaddr_in sa;
sa.sin_family = AF_INET;
if (inet_aton(host, (void*)&sa.sin_addr) == 0) {
struct hostent *he;
he = gethostbyname(host);
if (he == NULL) {
anetSetError(err, "can't resolve: %s", host);
return ANET_ERR;
}
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
}
strcpy(ipbuf,inet_ntoa(sa.sin_addr));
return ANET_OK;
}
static int anetCreateSocket(char *err, int domain) {
int s, on = 1;
if ((s = socket(domain, SOCK_STREAM, 0)) == -1) {
#ifdef _WIN32
errno = WSAGetLastError();
#endif
anetSetError(err, "creating socket: %s", strerror(errno));
return ANET_ERR;
}
@ -157,52 +147,63 @@ static int anetCreateSocket(char *err, int domain) {
#define ANET_CONNECT_NONE 0
#define ANET_CONNECT_NONBLOCK 1
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags)
static int anetTcpGenericConnect(char *err, char *addr, char *service, int flags)
{
int s;
struct sockaddr_in sa;
struct addrinfo gai_hints;
struct addrinfo *gai_result, *p;
int gai_error;
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
gai_hints.ai_family = AF_UNSPEC;
gai_hints.ai_socktype = SOCK_STREAM;
gai_hints.ai_protocol = 0;
gai_hints.ai_flags = 0;
gai_hints.ai_addrlen = 0;
gai_hints.ai_addr = NULL;
gai_hints.ai_canonname = NULL;
gai_hints.ai_next = NULL;
gai_error = getaddrinfo(addr, service, &gai_hints, &gai_result);
if (gai_error != 0) {
anetSetError(err, "can't resolve %s: %s", addr, gai_strerror(gai_error));
return ANET_ERR;
}
memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons((uint16_t)port);
if (inet_aton(addr, (void*)&sa.sin_addr) == 0) {
struct hostent *he;
for (p = gai_result; p != NULL; p = p->ai_next) {
if ((s = anetCreateSocket(err, p->ai_family)) == ANET_ERR)
continue;
he = gethostbyname(addr);
if (he == NULL) {
anetSetError(err, "can't resolve: %s", addr);
close(s);
return ANET_ERR;
if (flags & ANET_CONNECT_NONBLOCK) {
if (anetNonBlock(err,s) != ANET_OK)
return ANET_ERR;
}
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
}
if (flags & ANET_CONNECT_NONBLOCK) {
if (anetNonBlock(err,s) != ANET_OK)
return ANET_ERR;
}
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
if (errno == EINPROGRESS &&
flags & ANET_CONNECT_NONBLOCK)
if (connect(s, p->ai_addr, p->ai_addrlen) >= 0) {
freeaddrinfo(gai_result);
return s;
}
if (errno == EINPROGRESS && (flags & ANET_CONNECT_NONBLOCK)) {
freeaddrinfo(gai_result);
return s;
}
anetSetError(err, "connect: %s", strerror(errno));
close(s);
return ANET_ERR;
}
return s;
freeaddrinfo(gai_result);
return ANET_ERR;
}
int anetTcpConnect(char *err, char *addr, int port)
int anetTcpConnect(char *err, char *addr, char *service)
{
return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE);
return anetTcpGenericConnect(err,addr,service,ANET_CONNECT_NONE);
}
int anetTcpNonBlockConnect(char *err, char *addr, int port)
int anetTcpNonBlockConnect(char *err, char *addr, char *service)
{
return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK);
return anetTcpGenericConnect(err,addr,service,ANET_CONNECT_NONBLOCK);
}
/* Like read(2) but make sure 'count' is read before to return
@ -236,10 +237,12 @@ int anetWrite(int fd, char *buf, int count)
}
static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {
if (sa->sa_family == AF_INET6) {
int on = 1;
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
}
if (bind(s,sa,len) == -1) {
#ifdef _WIN32
errno = WSAGetLastError();
#endif
anetSetError(err, "bind: %s", strerror(errno));
close(s);
return ANET_ERR;
@ -249,9 +252,6 @@ static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {
* the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
* which will thus give us a backlog of 512 entries */
if (listen(s, 511) == -1) {
#ifdef _WIN32
errno = WSAGetLastError();
#endif
anetSetError(err, "listen: %s", strerror(errno));
close(s);
return ANET_ERR;
@ -259,40 +259,52 @@ static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {
return ANET_OK;
}
int anetTcpServer(char *err, int port, char *bindaddr)
int anetTcpServer(char *err, char *service, char *bindaddr, int *fds, int nfds)
{
int s;
struct sockaddr_in sa;
int i = 0;
struct addrinfo gai_hints;
struct addrinfo *gai_result, *p;
int gai_error;
if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR)
return ANET_ERR;
gai_hints.ai_family = AF_UNSPEC;
gai_hints.ai_socktype = SOCK_STREAM;
gai_hints.ai_protocol = 0;
gai_hints.ai_flags = AI_PASSIVE;
gai_hints.ai_addrlen = 0;
gai_hints.ai_addr = NULL;
gai_hints.ai_canonname = NULL;
gai_hints.ai_next = NULL;
memset(&sa,0,sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons((uint16_t)port);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (bindaddr && inet_aton(bindaddr, (void*)&sa.sin_addr) == 0) {
anetSetError(err, "invalid bind address");
close(s);
gai_error = getaddrinfo(bindaddr, service, &gai_hints, &gai_result);
if (gai_error != 0) {
anetSetError(err, "can't resolve %s: %s", bindaddr, gai_strerror(gai_error));
return ANET_ERR;
}
if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa)) == ANET_ERR)
return ANET_ERR;
return s;
for (p = gai_result; p != NULL && i < nfds; p = p->ai_next) {
if ((s = anetCreateSocket(err, p->ai_family)) == ANET_ERR)
continue;
if (anetListen(err, s, p->ai_addr, p->ai_addrlen) == ANET_ERR) {
continue;
}
fds[i++] = s;
}
freeaddrinfo(gai_result);
return (i > 0 ? i : ANET_ERR);
}
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len)
{
int fd;
while(1) {
fd = accept(s,sa,len);
if (fd == -1) {
#ifndef _WIN32
if (errno == EINTR) {
continue;
#else
errno = WSAGetLastError();
if (errno == WSAEWOULDBLOCK) {
#endif
} else {
anetSetError(err, "accept: %s", strerror(errno));
}
@ -302,44 +314,13 @@ static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *l
return fd;
}
int anetTcpAccept(char *err, int s, char *ip, int *port) {
int anetTcpAccept(char *err, int s) {
int fd;
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == ANET_ERR)
struct sockaddr_storage ss;
socklen_t sslen = sizeof(ss);
if ((fd = anetGenericAccept(err, s, (struct sockaddr*)&ss, &sslen)) == ANET_ERR)
return ANET_ERR;
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return fd;
}
int anetPeerToString(int fd, char *ip, int *port) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) {
*port = 0;
ip[0] = '?';
ip[1] = '\0';
return -1;
}
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return 0;
}
int anetSockName(int fd, char *ip, int *port) {
struct sockaddr_in sa;
socklen_t salen = sizeof(sa);
if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {
*port = 0;
ip[0] = '?';
ip[1] = '\0';
return -1;
}
if (ip) strcpy(ip,inet_ntoa(sa.sin_addr));
if (port) *port = ntohs(sa.sin_port);
return 0;
}

37
anet.h
View File

@ -1,3 +1,26 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// anet.h: Basic TCP socket stuff made a bit less boring
//
// Copyright (c) 2016 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file incorporates work covered by the following copyright and
// permission notice:
//
/* anet.c -- Basic TCP socket stuff made a bit less boring
*
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
@ -39,21 +62,15 @@
#define AF_LOCAL AF_UNIX
#endif
int anetTcpConnect(char *err, char *addr, int port);
int anetTcpNonBlockConnect(char *err, char *addr, int port);
int anetUnixConnect(char *err, char *path);
int anetUnixNonBlockConnect(char *err, char *path);
int anetTcpConnect(char *err, char *addr, char *service);
int anetTcpNonBlockConnect(char *err, char *addr, char *service);
int anetRead(int fd, char *buf, int count);
int anetResolve(char *err, char *host, char *ipbuf);
int anetTcpServer(char *err, int port, char *bindaddr);
int anetUnixServer(char *err, char *path, mode_t perm);
int anetTcpAccept(char *err, int serversock, char *ip, int *port);
int anetUnixAccept(char *err, int serversock);
int anetTcpServer(char *err, char *service, char *bindaddr, int *fds, int nfds);
int anetTcpAccept(char *err, int serversock);
int anetWrite(int fd, char *buf, int count);
int anetNonBlock(char *err, int fd);
int anetTcpNoDelay(char *err, int fd);
int anetTcpKeepAlive(char *err, int fd);
int anetPeerToString(int fd, char *ip, int *port);
int anetSetSendBuffer(char *err, int fd, int buffsize);
#endif

43
bladerf/README Normal file
View File

@ -0,0 +1,43 @@
bladeRF support
---------------
There is basic support for the bladeRF included in dump1090-fa.
It uses the same demodulator as the regular rtlsdr version and it does not
take advantage of the bladeRF's improved sampling rate or FPGA (but see below)
To use it:
$ dump1090-fa --device-type bladerf --gain 66 (.. other options ..)
The bladeRF has sensitivity problems when receiving ADS-B and will benefit
from all the gain you can give it. 66dB is the maximum configurable gain on
the board itself, you may want to add an external LNA too.
bladeRF custom FPGA bitstream
-----------------------------
The package includes a custom FPGA bitstream for the bladeRF which can
improve ADS-B reception with dump1090.
It adds a Fs/4 mixer step to avoid the DC offset of the bladeRF, and
decimate-by-8 downsampling step to improve sensitivity. Some of the bladeRF
parameters need to be adjusted so that it produces correctly tuned/downsampled
data in the form that dump1090 is expecting.
To use it:
$ dump1090-fa --device-type bladerf --gain 66 \
--bladerf-fpga /usr/share/dump1090-fa/bladerf/decimate8-x40.rbf \
--bladerf-decimation 8 \
--bladerf-bandwidth 14000000 \
--freq 1085200000 \
(other options ...)
The bladeRF will be configured for a 19.2MHz sampling rate and will tune to
1085.2MHz so that the 1090MHz signal appears around 4.8MHz in the baseband
samples. The FPGA Fs/4 mixing step shifts the baseband signal so that it is centered
around 0, and the FPGA downsampling step produces samples at 2.4MHz, which is what
dump1090 is expecting.
This FPGA bitstream is built for the 40kLE bladeRF.

BIN
bladerf/decimate8-x40.rbf Normal file

Binary file not shown.

6
coaa.h
View File

@ -1,6 +0,0 @@
// coaa.h configuration file for Plane Plotter Uploader
//
// You MUST apply via the COAA website for your own personal version of this file
// Do not disclose the contents of this file to anyone thereafter as it uniquely
// identifies you to the PlanePlotter system
//

Binary file not shown.

985
comm_b.c Normal file
View File

@ -0,0 +1,985 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// comm_b.c: Comm-B message decoding
//
// Copyright (c) 2017 FlightAware, LLC
// Copyright (c) 2017 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dump1090.h"
#include "ais_charset.h"
typedef int (*CommBDecoderFn)(struct modesMessage *,bool);
static int decodeEmptyResponse(struct modesMessage *mm, bool store);
static int decodeBDS10(struct modesMessage *mm, bool store);
static int decodeBDS17(struct modesMessage *mm, bool store);
static int decodeBDS20(struct modesMessage *mm, bool store);
static int decodeBDS30(struct modesMessage *mm, bool store);
static int decodeBDS40(struct modesMessage *mm, bool store);
static int decodeBDS44(struct modesMessage *mm, bool store);
static int decodeBDS50(struct modesMessage *mm, bool store);
static int decodeBDS60(struct modesMessage *mm, bool store);
static int decodeBDS05(struct modesMessage *mm, bool store);
static CommBDecoderFn comm_b_decoders[] = {
&decodeEmptyResponse,
&decodeBDS10,
&decodeBDS20,
&decodeBDS30,
&decodeBDS17,
&decodeBDS40,
&decodeBDS50,
&decodeBDS60,
&decodeBDS44,
&decodeBDS05
};
void decodeCommB(struct modesMessage *mm)
{
// If DR or UM are set, this message is _probably_ noise
// as nothing really seems to use the multisite broadcast stuff?
// Also skip anything that had errors corrected
if (mm->DR != 0 || mm->UM != 0 || mm->correctedbits > 0) {
mm->commb_format = COMMB_NOT_DECODED;
return;
}
// This is a bit hairy as we don't know what the requested register was
int bestScore = 0;
CommBDecoderFn bestDecoder = NULL;
int ambiguous = 0;
for (unsigned i = 0; i < (sizeof(comm_b_decoders) / sizeof(comm_b_decoders[0])); ++i) {
int score = comm_b_decoders[i](mm, false);
if (score > bestScore) {
bestScore = score;
bestDecoder = comm_b_decoders[i];
ambiguous = 0;
} else if (score == bestScore) {
ambiguous = 1;
}
}
if (bestDecoder) {
if (ambiguous) {
mm->commb_format = COMMB_AMBIGUOUS;
} else {
// decode it
bestDecoder(mm, true);
}
} else {
mm->commb_format = COMMB_UNKNOWN;
}
}
static int decodeEmptyResponse(struct modesMessage *mm, bool store)
{
// 00000000000000 is a common response. Ignore it.
//
// Also, it's common to see responses that look like this:
// 40000000000000
// 50000000000000
// 60000000000000
// typically in grouped bursts (one of each message) from
// the same aircraft.
//
// I speculate that these are response to interrogations for
// BDS 4,0 5,0 and 6,0 respectively where the transponder
// doesn't support the register or has no data loaded for it.
// Treat them like empty responses.
switch (mm->MB[0]) {
case 0x00:
case 0x40:
case 0x50:
case 0x60:
break;
default:
return 0;
}
for (unsigned i = 1; i < 7; ++i) {
if (mm->MB[i] != 0) {
return 0;
}
}
if (store) {
mm->commb_format = COMMB_EMPTY_RESPONSE;
}
return 56;
}
// BDS1,0 Datalink capabilities
static int decodeBDS10(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
// BDS identifier
if (msg[0] != 0x10) {
return 0;
}
// Reserved bits
if (getbits(msg, 10, 14) != 0) {
return 0;
}
// Looks plausible.
if (store) {
mm->commb_format = COMMB_DATALINK_CAPS;
}
return 56;
}
// BDS1,7 Common usage GICB capability report
static int decodeBDS17(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
// reserved bits
if (getbits(msg, 25, 56) != 0) {
return 0;
}
int score = 0;
if (getbit(msg, 7)) {
score += 1; // 2,0 aircraft identification
} else {
// BDS2,0 is on almost everything
score -= 2;
}
// unlikely bits
if (getbit(msg, 10)) { // 4,1 next waypoint identifier
score -= 2;
}
if (getbit(msg, 11)) { // 4,2 next waypoint position
score -= 2;
}
if (getbit(msg, 12)) { // 4,3 next waypoint information
score -= 2;
}
if (getbit(msg, 13)) { // 4,4 meterological routine report
score -= 1;
}
if (getbit(msg, 14)) { // 4,4 meterological hazard report
score -= 1;
}
if (getbit(msg, 20)) { // 5,4 waypoint 1
score -= 2;
}
if (getbit(msg, 21)) { // 5,5 waypoint 2
score -= 2;
}
if (getbit(msg, 22)) { // 5,6 waypoint 3
score -= 2;
}
if (getbit(msg, 1) && getbit(msg, 2) && getbit(msg, 3) && getbit(msg, 4) && getbit(msg, 5)) {
// looks like ES capable
score += 5;
if (getbit(msg, 6)) {
// ES EDI
score += 1;
}
} else if (!getbit(msg, 1) && !getbit(msg, 2) && !getbit(msg, 3) && !getbit(msg, 4) && !getbit(msg, 5) && !getbit(msg, 6)) {
// not ES capable
score += 1;
} else if (!getbit(msg, 1) && !getbit(msg, 2) && getbit(msg, 3) && getbit(msg, 4) && getbit(msg, 5)) {
// ES with no position data
score += 3;
} else {
// other combinations, unlikely
score -= 12;
}
if (getbit(msg, 16) && getbit(msg, 24)) {
// track/turn, heading/speed
score += 2;
if (getbit(msg, 9)) {
// vertical intent
score += 1;
}
} else if (!getbit(msg, 16) && !getbit(msg, 24) && !getbit(msg, 9)) {
// neither
score += 1;
} else {
// unlikely
score -= 6;
}
if (store) {
mm->commb_format = COMMB_GICB_CAPS;
}
return score;
}
// BDS2,0 Aircraft identification
static int decodeBDS20(struct modesMessage *mm, bool store)
{
char callsign[9];
unsigned char *msg = mm->MB;
// BDS identifier
if (msg[0] != 0x20) {
return 0;
}
callsign[0] = ais_charset[getbits(msg, 9, 14)];
callsign[1] = ais_charset[getbits(msg, 15, 20)];
callsign[2] = ais_charset[getbits(msg, 21, 26)];
callsign[3] = ais_charset[getbits(msg, 27, 32)];
callsign[4] = ais_charset[getbits(msg, 33, 38)];
callsign[5] = ais_charset[getbits(msg, 39, 44)];
callsign[6] = ais_charset[getbits(msg, 45, 50)];
callsign[7] = ais_charset[getbits(msg, 51, 56)];
callsign[8] = 0;
// score based on number of valid characters
int score = 8;
int valid = 1;
for (unsigned i = 0; i < 8; ++i) {
if ((callsign[i] >= 'A' && callsign[i] <= 'Z') || (callsign[i] >= '0' && callsign[i] <= '9') || callsign[i] == ' ') {
score += 6;
} else if (callsign[i] == '@') {
// Padding (sometimes we get @@@@@@@@, i.e. BDS2,0 with all zeros - we do want to accept this as a BDS2,0 but not actually use the callsign)
valid = 0;
} else {
// Invalid
return 0;
}
}
if (store) {
mm->commb_format = COMMB_AIRCRAFT_IDENT;
if (valid) {
memcpy(mm->callsign, callsign, sizeof(mm->callsign));
mm->callsign_valid = 1;
}
}
return score;
}
// BDS3,0 ACAS RA
static int decodeBDS30(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
// BDS identifier
if (msg[0] != 0x30) {
return 0;
}
if (store) {
mm->commb_format = COMMB_ACAS_RA;
}
// just accept it.
return 56;
}
// BDS4,0 Selected vertical intention
static int decodeBDS40(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
unsigned mcp_valid = getbit(msg, 1);
unsigned mcp_raw = getbits(msg, 2, 13);
unsigned fms_valid = getbit(msg, 14);
unsigned fms_raw = getbits(msg, 15, 26);
unsigned baro_valid = getbit(msg, 27);
unsigned baro_raw = getbits(msg, 28, 39);
unsigned reserved_1 = getbits(msg, 40, 47);
unsigned mode_valid = getbit(msg, 48);
unsigned mode_raw = getbits(msg, 49, 51);
unsigned reserved_2 = getbits(msg, 52, 53);
unsigned source_valid = getbit(msg, 54);
unsigned source_raw = getbits(msg, 55, 56);
if (!mcp_valid && !fms_valid && !baro_valid && !mode_valid && !source_valid) {
return 0;
}
int score = 0;
unsigned mcp_alt = 0;
if (mcp_valid && mcp_raw != 0) {
mcp_alt = mcp_raw * 16;
if (mcp_alt >= 1000 && mcp_alt <= 50000) {
score += 13;
} else {
// unlikely altitude
return 0;
}
} else if (!mcp_valid && mcp_raw == 0) {
score += 1;
} else {
return 0;
}
unsigned fms_alt = 0;
if (fms_valid && fms_raw != 0) {
fms_alt = fms_raw * 16;
if (fms_alt >= 1000 && fms_alt <= 50000) {
score += 13;
} else {
// unlikely altitude
return 0;
}
} else if (!fms_valid && fms_raw == 0) {
score += 1;
} else {
return 0;
}
float baro_setting = 0;
if (baro_valid && baro_raw != 0) {
baro_setting = 800 + baro_raw * 0.1;
if (baro_setting >= 900 && baro_setting <= 1100) {
score += 13;
} else {
// unlikely pressure setting
return 0;
}
} else if (!baro_valid && baro_raw == 0) {
score += 1;
} else {
return 0;
}
if (reserved_1 != 0) {
return 0;
}
if (mode_valid) {
score += 4;
} else if (!mode_valid && mode_raw == 0) {
score += 1;
} else {
return 0;
}
if (reserved_2 != 0) {
return 0;
}
if (source_valid) {
score += 3;
} else if (!source_valid && source_raw == 0) {
score += 1;
} else {
return 0;
}
// small penalty for inconsistent data
if (mcp_valid && fms_valid && mcp_alt != fms_alt) {
score -= 4;
}
if (mcp_valid) {
unsigned remainder = mcp_alt % 500;
if (!(remainder < 16 || remainder > 484)) {
// mcp altitude is not a multiple of 500
score -= 4;
}
}
if (fms_valid) {
unsigned remainder = fms_alt % 500;
if (!(remainder < 16 || remainder > 484)) {
// fms altitude is not a multiple of 500
score -= 4;
}
}
if (store) {
mm->commb_format = COMMB_VERTICAL_INTENT;
if (mcp_valid) {
mm->nav.mcp_altitude_valid = 1;
mm->nav.mcp_altitude = mcp_alt;
}
if (fms_valid) {
mm->nav.fms_altitude_valid = 1;
mm->nav.fms_altitude = fms_alt;
}
if (baro_valid) {
mm->nav.qnh_valid = 1;
mm->nav.qnh = baro_setting;
}
if (mode_valid) {
mm->nav.modes_valid = 1;
mm->nav.modes =
((mode_raw & 4) ? NAV_MODE_VNAV : 0) |
((mode_raw & 2) ? NAV_MODE_ALT_HOLD : 0) |
((mode_raw & 1) ? NAV_MODE_APPROACH : 0);
}
if (source_valid) {
switch (source_raw) {
case 0:
mm->nav.altitude_source = NAV_ALT_UNKNOWN;
break;
case 1:
mm->nav.altitude_source = NAV_ALT_AIRCRAFT;
break;
case 2:
mm->nav.altitude_source = NAV_ALT_MCP;
break;
case 3:
mm->nav.altitude_source = NAV_ALT_FMS;
break;
default:
mm->nav.altitude_source = NAV_ALT_INVALID;
break;
}
} else {
mm->nav.altitude_source = NAV_ALT_INVALID;
}
}
return score;
}
// BDS5,0 Track and turn report
static int decodeBDS50(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
unsigned roll_valid = getbit(msg, 1);
unsigned roll_sign = getbit(msg, 2);
unsigned roll_raw = getbits(msg, 3, 11);
unsigned track_valid = getbit(msg, 12);
unsigned track_sign = getbit(msg, 13);
unsigned track_raw = getbits(msg, 14, 23);
unsigned gs_valid = getbit(msg, 24);
unsigned gs_raw = getbits(msg, 25, 34);
unsigned track_rate_valid = getbit(msg, 35);
unsigned track_rate_sign = getbit(msg, 36);
unsigned track_rate_raw = getbits(msg, 37, 45);
unsigned tas_valid = getbit(msg, 46);
unsigned tas_raw = getbits(msg, 47, 56);
if (!roll_valid || !track_valid || !gs_valid || !tas_valid) {
return 0;
}
int score = 0;
float roll = 0;
if (roll_valid) {
roll = roll_raw * 45.0 / 256.0;
if (roll_sign) {
roll -= 90.0;
}
if (roll >= -40 && roll < 40) {
score += 11;
} else {
return 0;
}
} else if (!roll_valid && roll_raw == 0 && !roll_sign) {
score += 1;
} else {
return 0;
}
float track = 0;
if (track_valid) {
score += 12;
track = track_raw * 90.0 / 512.0;
if (track_sign) {
track += 180.0;
}
} else if (!track_valid && track_raw == 0 && !track_sign) {
score += 1;
} else {
return 0;
}
unsigned gs = 0;
if (gs_valid && gs_raw != 0) {
gs = gs_raw * 2;
if (gs >= 50 && gs <= 700) {
score += 11;
} else {
return 0;
}
} else if (!gs_valid && gs_raw == 0) {
score += 1;
} else {
return 0;
}
float track_rate = 0;
if (track_rate_valid) {
track_rate = track_rate_raw * 8.0 / 256.0;
if (track_rate_sign) {
track_rate -= 16;
}
if (track_rate >= -10.0 && track_rate <= 10.0) {
score += 11;
} else {
return 0;
}
} else if (!track_rate_valid && track_rate_raw == 0 && !track_rate_sign) {
score += 1;
} else {
return 0;
}
unsigned tas = 0;
if (tas_valid && tas_raw != 0) {
tas = tas_raw * 2;
if (tas >= 50 && tas <= 700) {
score += 11;
} else {
return 0;
}
} else if (!tas_valid && tas_raw == 0) {
score += 1;
} else {
return 0;
}
// small penalty for inconsistent data
if (gs_valid && tas_valid) {
int delta = abs((int)gs_valid - (int)tas_valid);
if (delta > 150) {
score -= 6;
}
}
// compute the theoretical turn rate and compare to track angle rate
if (roll_valid && tas_valid && tas > 0 && track_rate_valid) {
double turn_rate = 68625 * tan(roll * M_PI / 180.0) / (tas * 20 * M_PI);
double delta = fabs(turn_rate - track_rate);
if (delta > 2.0) {
score -= 6;
}
}
if (store) {
mm->commb_format = COMMB_TRACK_TURN;
if (roll_valid) {
mm->roll_valid = 1;
mm->roll = roll;
}
if (track_valid) {
mm->heading_valid = 1;
mm->heading = track;
mm->heading_type = HEADING_GROUND_TRACK;
}
if (gs_valid) {
mm->gs_valid = 1;
mm->gs.v0 = mm->gs.v2 = mm->gs.selected = gs;
}
if (track_rate_valid) {
mm->track_rate_valid = 1;
mm->track_rate = track_rate;
}
if (tas_valid) {
mm->tas_valid = 1;
mm->tas = tas;
}
}
return score;
}
// BDS6,0 Heading and speed report
static int decodeBDS60(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
unsigned heading_valid = getbit(msg, 1);
unsigned heading_sign = getbit(msg, 2);
unsigned heading_raw = getbits(msg, 3, 12);
unsigned ias_valid = getbit(msg, 13);
unsigned ias_raw = getbits(msg, 14, 23);
unsigned mach_valid = getbit(msg, 24);
unsigned mach_raw = getbits(msg, 25, 34);
unsigned baro_rate_valid = getbit(msg, 35);
unsigned baro_rate_sign = getbit(msg, 36);
unsigned baro_rate_raw = getbits(msg, 37, 45);
unsigned inertial_rate_valid = getbit(msg, 46);
unsigned inertial_rate_sign = getbit(msg, 47);
unsigned inertial_rate_raw = getbits(msg, 48, 56);
if (!heading_valid || !ias_valid || !mach_valid || (!baro_rate_valid && !inertial_rate_valid)) {
return 0;
}
int score = 0;
float heading = 0;
if (heading_valid) {
heading = heading_raw * 90.0 / 512.0;
if (heading_sign) {
heading += 180.0;
}
score += 12;
} else if (!heading_valid && heading_raw == 0 && !heading_sign) {
score += 1;
} else {
return 0;
}
unsigned ias = 0;
if (ias_valid && ias_raw != 0) {
ias = ias_raw;
if (ias >= 50 && ias <= 700) {
score += 11;
} else {
return 0;
}
} else if (!ias_valid && ias_raw == 0) {
score += 1;
} else {
return 0;
}
float mach = 0;
if (mach_valid && mach_raw != 0) {
mach = mach_raw * 2.048 / 512;
if (mach >= 0.1 && mach <= 0.9) {
score += 11;
} else {
return 0;
}
} else if (!mach_valid && mach_raw == 0) {
score += 1;
} else {
return 0;
}
int baro_rate = 0;
if (baro_rate_valid) {
baro_rate = baro_rate_raw * 32;
if (baro_rate_sign) {
baro_rate -= 16384;
}
if (baro_rate >= -6000 && baro_rate <= 6000) {
score += 11;
} else {
return 0;
}
} else if (!baro_rate_valid && baro_rate_raw == 0) {
score += 1;
} else {
return 0;
}
int inertial_rate = 0;
if (inertial_rate_valid) {
inertial_rate = inertial_rate_raw * 32;
if (inertial_rate_sign) {
inertial_rate -= 16384;
}
if (inertial_rate >= -6000 && inertial_rate <= 6000) {
score += 11;
} else {
return 0;
}
} else if (!inertial_rate_valid && inertial_rate_raw == 0) {
score += 1;
} else {
return 0;
}
// small penalty for inconsistent data
// Should check IAS vs Mach at given altitude, but the maths is a little involved
if (baro_rate_valid && inertial_rate_valid) {
int delta = abs(baro_rate - inertial_rate);
if (delta > 2000) {
score -= 12;
}
}
if (store) {
mm->commb_format = COMMB_HEADING_SPEED;
if (heading_valid) {
mm->heading_valid = 1;
mm->heading = heading;
mm->heading_type = HEADING_MAGNETIC;
}
if (ias_valid) {
mm->ias_valid = 1;
mm->ias = ias;
}
if (mach_valid) {
mm->mach_valid = 1;
mm->mach = mach;
}
if (baro_rate_valid) {
mm->baro_rate_valid = 1;
mm->baro_rate = baro_rate;
}
if (inertial_rate_valid) {
// INS-derived data is treated as a "geometric rate" / "geometric altitude"
// elsewhere, so do the same here.
mm->geom_rate_valid = 1;
mm->geom_rate = inertial_rate;
}
}
return score;
}
// BDS4,4 Meterological routine air report
static int decodeBDS44(struct modesMessage *mm, bool store)
{
unsigned char *msg = mm->MB;
unsigned source = getbits(msg, 1, 4);
unsigned wind_valid = getbit(msg, 5);
unsigned windspeed_raw = getbits(msg, 6, 14);
unsigned winddir_raw = getbits(msg, 15, 23);
// ICAO 9871 is inconsistent, it claims:
// bit 24 sign
// bits 25..34 static air temperature, MSB = 64C, LSB=0.25C, range -128C..+128C
//
// .. but this does not actually work, there is one too many bits in the bitfield
// for the claimed values.
//
// Based on observed data, the most plausible actual layout is:
//
// bit 24 status
// bit 25 sign
// bits 26..34 static air temperature, MSB=64C, LSB=0.25C, range -128C..+128C
unsigned sat_valid = getbit(msg, 24);
unsigned sat_sign = getbit(msg, 25);
unsigned sat_raw = getbits(msg, 26, 34);
unsigned asp_valid = getbit(msg, 35);
unsigned asp_raw = getbits(msg, 36, 46);
unsigned turbulence_valid = getbit(msg, 47);
unsigned turbulence_raw = getbits(msg, 48, 49);
unsigned humidity_valid = getbit(msg, 50);
unsigned humidity_raw = getbits(msg, 51, 56);
if (source == MRAR_SOURCE_INVALID || source >= MRAR_SOURCE_RESERVED)
return 0; // invalid or reserved source
if (!wind_valid || !sat_valid)
return 0; // all valid messages seen in the wild have at least temp + wind
if (!asp_valid && asp_raw != 0)
return 0; // ASP not valid, but non-zero values in the ASP field
if (!turbulence_valid && turbulence_raw != 0)
return 0; // turbulence not valid, but non-zero values in the turbulence field
if (!humidity_valid && humidity_raw != 0)
return 0; // humidity not valid, but non-zero values in the humidity field
int score = 0;
float wind_speed = 0;
float wind_dir = 0;
if (wind_valid) {
wind_dir = winddir_raw * (180.0 / 256.0);
wind_speed = windspeed_raw;
if (windspeed_raw == 0) // possible but uncommon
score += 2;
else if (wind_speed <= 250)
score += 19;
else
return 0;
} else {
score += 1;
}
float sat = 0;
if (sat_valid) {
sat = sat_raw * 0.25;
if (sat_sign)
sat -= 128;
if (sat == 0) // possible but uncommon
score += 2;
else if (sat >= -80 && sat <= 60)
score += 11;
else
return 0;
} else {
score += 1;
}
float asp = 0;
if (asp_valid) {
asp = asp_raw;
if (asp >= 25 && asp <= 1100)
score += 12;
else
return 0;
} else {
score += 1;
}
hazard_t turbulence = HAZARD_NIL;
if (turbulence_valid) {
turbulence = (hazard_t) turbulence_raw;
score += 3;
} else {
score += 1;
}
float humidity = 0;
if (humidity_valid) {
humidity = humidity_raw * (100.0 / 64.0);
score += 7;
} else {
score += 1;
}
if (source == MRAR_SOURCE_DMEDME && wind_valid && sat_valid && score > 0) {
// Some GICB messages can be easily mistaken for a MRAR:
//
// GICB bit 1: BDS 0,5 ES airborne position = 0 ]
// GICB bit 2: BDS 0,6 ES surface position = 0 ]
// GICB bit 3: BDS 0,7 ES status = 1 ]
// GICB bit 4: BDS 0,8 ES type & identification = 1 ] -> MRAR source = 3
// GICB bit 5: BDS 0,9 ES airborne velocity = 1 -> MRAR wind valid bit
// GICB bit 24: BDS 6,0 heading and speed report = 1 -> MRAR temp valid bit
// most trailing bits = 0
//
// so only treat this as MRAR as a last resort
score = 1;
}
if (store) {
mm->commb_format = COMMB_MRAR;
mm->mrar_source_valid = 1;
mm->mrar_source = (mrar_source_t) source;
if (wind_valid) {
mm->wind_valid = 1;
mm->wind_speed = wind_speed;
mm->wind_dir = wind_dir;
}
if (sat_valid) {
mm->temperature_valid = 1;
mm->temperature = sat;
}
if (asp_valid) {
mm->pressure_valid = 1;
mm->pressure = asp;
}
if (turbulence_valid) {
mm->turbulence_valid = 1;
mm->turbulence = turbulence;
}
if (humidity_valid) {
mm->humidity_valid = 1;
mm->humidity = humidity;
}
}
return score;
}
// BDS0,5 extended squitter airborne position
// (apparently this gets queried via comm-b sometimes??)
// We don't try to _use_ this as a position, but we can
// at least try to recognize it, to exclude other
// comm-b types (in particular they can be mistaken for MRAR)
static int decodeBDS05(struct modesMessage *mm, bool store)
{
// We recognize these by matching the position altitude against
// the altitude in the surrounding message, so we need a
// DF20 not a DF21
if (mm->msgtype != 20)
return 0;
unsigned char *msg = mm->MB;
unsigned typecode = getbits(msg, 1, 5);
if (typecode < 9 || typecode > 18)
return 0; // only consider typecodes that could be an airborne position with baro altitude
unsigned t_bit = getbit(msg, 21);
if (t_bit) // unlikely
return 0;
unsigned ac12 = getbits(msg, 9, 20);
if (!ac12)
return 0;
// Insert M=0 to make an AC13 value, match against the
// AC13 value in the surrounding message
unsigned ac13 = ((ac12 & 0x0FC0) << 1) | (ac12 & 0x003F);
if (mm->AC != ac13)
return 0; // no altitude match
unsigned lat = getbits(msg, 23, 39);
unsigned lon = getbits(msg, 40, 56);
if (lat == 0 || lon == 0) // unlikely position
return 0;
if (store) {
mm->commb_format = COMMB_AIRBORNE_POSITION;
// No further decoding done, we don't really trust this
// enough to use as real input to CPR
}
// Score this high enough to override everything else
return 100;
}

26
comm_b.h Normal file
View File

@ -0,0 +1,26 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// comm_b.h: Comm-B message decoding (prototypes)
//
// Copyright (c) 2017 FlightAware, LLC
// Copyright (c) 2017 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef COMM_B_H
#define COMM_B_H
void decodeCommB(struct modesMessage *mm);
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright (c), MM Weiss
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the MM Weiss nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

View File

@ -0,0 +1,138 @@
/*
* Copyright (c), MM Weiss
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the MM Weiss nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* clock_gettime_stub.c
* gcc -Wall -c clock_gettime_stub.c
* posix realtime functions; MacOS user space glue
*/
/* @comment
* other possible implementation using intel builtin rdtsc
* rdtsc-workaround: http://www.mcs.anl.gov/~kazutomo/rdtsc.html
*
* we could get the ticks by doing this
*
* __asm __volatile("mov %%ebx, %%esi\n\t"
* "cpuid\n\t"
* "xchg %%esi, %%ebx\n\t"
* "rdtsc"
* : "=a" (a),
* "=d" (d)
* );
* we could even replace our tricky sched_yield call by assembly code to get a better accurency,
* anyway the following C stub will satisfy 99% of apps using posix clock_gettime call,
* moreover, the setter version (clock_settime) could be easly written using mach primitives:
* http://www.opensource.apple.com/source/xnu/xnu-${VERSION}/osfmk/man/ (clock_[set|get]_time)
*
* hackers don't be crackers, don't you use a flush toilet?
*
*
* @see draft: ./posix-realtime-stub/posix-realtime-stub.c
*
*/
#include "../compat.h"
#include <mach/mach_time.h>
#include <mach/clock.h> // for clock_get_time
#include <mach/clock_types.h> // for mach_timespec_t, CALENDAR_CLOCK, etc
#include <mach/kern_return.h> // for KERN_SUCCESS, kern_return_t
#include <mach/mach_host.h> // for host_get_clock_service
#include <mach/mach_init.h> // for mach_host_self
#include <mach/mach_types.h> // for clock_serv_t
#include <sched.h> // for sched_yield
#include <errno.h> // for EINVAL, errno
#include <unistd.h> // for getpid
static mach_timebase_info_data_t __clock_gettime_inf;
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
kern_return_t ret;
clock_serv_t clk;
clock_id_t clk_serv_id;
mach_timespec_t tm;
uint64_t start, end, delta, nano;
/*
task_basic_info_data_t tinfo;
task_thread_times_info_data_t ttinfo;
mach_msg_type_number_t tflag;
*/
int retval = -1;
switch (clk_id)
{
case CLOCK_REALTIME:
case CLOCK_MONOTONIC:
clk_serv_id = clk_id == CLOCK_REALTIME ? CALENDAR_CLOCK : SYSTEM_CLOCK;
if (KERN_SUCCESS == (ret = host_get_clock_service(mach_host_self(), clk_serv_id, &clk)))
{
if (KERN_SUCCESS == (ret = clock_get_time(clk, &tm)))
{
tp->tv_sec = tm.tv_sec;
tp->tv_nsec = tm.tv_nsec;
retval = 0;
}
}
if (KERN_SUCCESS != ret)
{
errno = EINVAL;
retval = -1;
}
break;
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_THREAD_CPUTIME_ID:
start = mach_absolute_time();
if (clk_id == CLOCK_PROCESS_CPUTIME_ID)
{
getpid();
}
else
{
sched_yield();
}
end = mach_absolute_time();
delta = end - start;
if (0 == __clock_gettime_inf.denom)
{
mach_timebase_info(&__clock_gettime_inf);
}
nano = delta * __clock_gettime_inf.numer / __clock_gettime_inf.denom;
tp->tv_sec = nano * 1e-9;
tp->tv_nsec = nano - (tp->tv_sec * 1e9);
retval = 0;
break;
default:
errno = EINVAL;
retval = -1;
}
return retval;
}

View File

@ -0,0 +1,6 @@
#ifndef CLOCK_GETTIME_H
#define CLOCK_GETTIME_H
int clock_gettime(clockid_t clk_id, struct timespec *tp);
#endif // CLOCK_GETTIME_H

View File

@ -0,0 +1,16 @@
/***********************************************************************
* Copyright © 2006 Rémi Denis-Courmont. *
* This program is free software; you can redistribute and/or modify *
* it under the terms of the GNU General Public License as published *
* by the Free Software Foundation; version 2 of the license, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, you can get it from: *
* http://www.gnu.org/copyleft/gpl.html *
***********************************************************************/

View File

@ -0,0 +1,62 @@
/*
* clock_nanosleep.c - clock_nanosleep() replacement
*/
/***********************************************************************
* Copyright © 2006 Rémi Denis-Courmont. *
* This program is free software; you can redistribute and/or modify *
* it under the terms of the GNU General Public License as published *
* by the Free Software Foundation; version 2 of the license, or (at *
* your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, you can get it from: *
* http://www.gnu.org/copyleft/gpl.html *
***********************************************************************/
#include <errno.h> // for errno, EINVAL
#include <time.h> // for nanosleep, NULL
#include "../compat.h"
int clock_nanosleep(clockid_t id, int flags, const struct timespec *ts,
struct timespec *ots) {
int ret;
if (id != CLOCK_REALTIME)
return EINVAL;
if (flags & TIMER_ABSTIME) {
struct timespec mine;
if (clock_gettime(id, &mine))
return errno;
if (mine.tv_sec > ts->tv_sec)
return 0; // behind schedule
if (mine.tv_nsec > ts->tv_nsec) {
if (mine.tv_sec == ts->tv_sec)
return 0; // behind schedule too
mine.tv_nsec = 1000000000 + ts->tv_nsec - mine.tv_nsec;
mine.tv_sec++;
}
else
mine.tv_nsec = ts->tv_nsec - mine.tv_nsec;
mine.tv_sec = ts->tv_sec - mine.tv_sec;
/* With TIMER_ABSTIME, clock_nanosleep ignores <ots> */
ret = nanosleep(&mine, NULL);
}
else
ret = nanosleep(ts, ots);
return ret ? errno : 0;
}

View File

@ -0,0 +1,7 @@
#ifndef CLOCK_NANOSLEEP_H
#define CLOCK_NANOSLEEP_H
int clock_nanosleep (clockid_t id, int flags, const struct timespec *ts,
struct timespec *ots);
#endif //CLOCK_NANOSLEEP_H

63
compat/compat.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef COMPAT_UTIL_H
#define COMPAT_UTIL_H
/*
* Platform-specific bits
*/
#if defined(__APPLE__)
/*
* Mach endian conversion
*/
# include <libkern/OSByteOrder.h>
# define bswap_16 OSSwapInt16
# define bswap_32 OSSwapInt32
# define bswap_64 OSSwapInt64
# include <machine/endian.h>
# define le16toh(x) OSSwapLittleToHostInt16(x)
# define le32toh(x) OSSwapLittleToHostInt32(x)
# define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#else // other platforms
# include <endian.h>
#endif
/* clock_* and time-related types */
#include <time.h>
#if defined(CLOCK_REALTIME)
# define HAVE_CLOCKID_T
#endif
#ifndef HAVE_CLOCKID_T
typedef enum
{
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID
} clockid_t;
#endif // !HAVE_CLOCKID_T
#ifndef TIMER_ABSTIME
#define TIMER_ABSTIME 1
#endif // !TIMER_ABSTIME
struct timespec;
#ifdef MISSING_NANOSLEEP
#include "clock_nanosleep/clock_nanosleep.h"
#endif
#ifdef MISSING_GETTIME
#include "clock_gettime/clock_gettime.h"
#endif
#endif //COMPAT_UTIL_H

123
convert.c Normal file
View File

@ -0,0 +1,123 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// convert.c: support for various IQ -> magnitude conversions
//
// Copyright (c) 2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dump1090.h"
static void convert_uc8(void *iq_data,
uint16_t *mag_data,
unsigned nsamples,
struct converter_state *state,
double *out_mean_level,
double *out_mean_power)
{
MODES_NOTUSED(state);
const uc8_t *in = (const uc8_t *) iq_data;
if (out_mean_level && out_mean_power) {
if (STARCH_IS_ALIGNED(in) && STARCH_IS_ALIGNED(mag_data))
starch_magnitude_power_uc8_aligned(in, mag_data, nsamples, out_mean_level, out_mean_power);
else
starch_magnitude_power_uc8(in, mag_data, nsamples, out_mean_level, out_mean_power);
} else {
if (STARCH_IS_ALIGNED(in) && STARCH_IS_ALIGNED(mag_data))
starch_magnitude_uc8_aligned(in, mag_data, nsamples);
else
starch_magnitude_uc8(in, mag_data, nsamples);
}
}
static void convert_sc16(void *iq_data,
uint16_t *mag_data,
unsigned nsamples,
struct converter_state *state,
double *out_mean_level,
double *out_mean_power)
{
MODES_NOTUSED(state);
const sc16_t *in = (const sc16_t *) iq_data;
if (STARCH_IS_ALIGNED(in) && STARCH_IS_ALIGNED(mag_data))
starch_magnitude_sc16_aligned(in, mag_data, nsamples);
else
starch_magnitude_sc16(in, mag_data, nsamples);
if (out_mean_level && out_mean_power) {
if (STARCH_IS_ALIGNED(mag_data))
starch_mean_power_u16_aligned(mag_data, nsamples, out_mean_level, out_mean_power);
else
starch_mean_power_u16(mag_data, nsamples, out_mean_level, out_mean_power);
}
}
static void convert_sc16q11(void *iq_data,
uint16_t *mag_data,
unsigned nsamples,
struct converter_state *state,
double *out_mean_level,
double *out_mean_power)
{
MODES_NOTUSED(state);
const sc16_t *in = (const sc16_t *) iq_data;
if (STARCH_IS_ALIGNED(in) && STARCH_IS_ALIGNED(mag_data))
starch_magnitude_sc16q11_aligned(in, mag_data, nsamples);
else
starch_magnitude_sc16q11(in, mag_data, nsamples);
if (out_mean_level && out_mean_power) {
if (STARCH_IS_ALIGNED(mag_data))
starch_mean_power_u16_aligned(mag_data, nsamples, out_mean_level, out_mean_power);
else
starch_mean_power_u16(mag_data, nsamples, out_mean_level, out_mean_power);
}
}
iq_convert_fn init_converter(input_format_t format,
double sample_rate,
int filter_dc,
struct converter_state **out_state)
{
MODES_NOTUSED(sample_rate);
MODES_NOTUSED(out_state);
if (filter_dc) {
fprintf(stderr, "DC filtering not supported (yet)\n");
return NULL;
}
switch (format) {
case INPUT_UC8:
return convert_uc8;
case INPUT_SC16:
return convert_sc16;
case INPUT_SC16Q11:
return convert_sc16q11;
default:
fprintf(stderr, "no suitable converter for format=%d\n", format);
return NULL;
}
}
void cleanup_converter(struct converter_state *state)
{
MODES_NOTUSED(state);
}

40
convert.h Normal file
View File

@ -0,0 +1,40 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// convert.h: support for various IQ -> magnitude conversions
//
// Copyright (c) 2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef DUMP1090_CONVERT_H
#define DUMP1090_CONVERT_H
struct converter_state;
typedef enum { INPUT_UC8=0, INPUT_SC16, INPUT_SC16Q11 } input_format_t;
typedef void (*iq_convert_fn)(void *iq_data,
uint16_t *mag_data,
unsigned nsamples,
struct converter_state *state,
double *out_mean_level,
double *out_mean_power);
iq_convert_fn init_converter(input_format_t format,
double sample_rate,
int filter_dc,
struct converter_state **out_state);
void cleanup_converter(struct converter_state *state);
#endif

369
cpr.c Normal file
View File

@ -0,0 +1,369 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// cpr.c - Compact Position Reporting decoder and tests
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file incorporates work covered by the following copyright and
// permission notice:
//
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "cpr.h"
#include <math.h>
#include <stdio.h>
//
//=========================================================================
//
// Always positive MOD operation, used for CPR decoding.
//
static int cprModInt(int a, int b) {
int res = a % b;
if (res < 0) res += b;
return res;
}
static double cprModDouble(double a, double b) {
double res = fmod(a, b);
if (res < 0) res += b;
return res;
}
//
//=========================================================================
//
// The NL function uses the precomputed table from 1090-WP-9-14
//
static int cprNLFunction(double lat) {
if (lat < 0) lat = -lat; // Table is simmetric about the equator
if (lat < 10.47047130) return 59;
if (lat < 14.82817437) return 58;
if (lat < 18.18626357) return 57;
if (lat < 21.02939493) return 56;
if (lat < 23.54504487) return 55;
if (lat < 25.82924707) return 54;
if (lat < 27.93898710) return 53;
if (lat < 29.91135686) return 52;
if (lat < 31.77209708) return 51;
if (lat < 33.53993436) return 50;
if (lat < 35.22899598) return 49;
if (lat < 36.85025108) return 48;
if (lat < 38.41241892) return 47;
if (lat < 39.92256684) return 46;
if (lat < 41.38651832) return 45;
if (lat < 42.80914012) return 44;
if (lat < 44.19454951) return 43;
if (lat < 45.54626723) return 42;
if (lat < 46.86733252) return 41;
if (lat < 48.16039128) return 40;
if (lat < 49.42776439) return 39;
if (lat < 50.67150166) return 38;
if (lat < 51.89342469) return 37;
if (lat < 53.09516153) return 36;
if (lat < 54.27817472) return 35;
if (lat < 55.44378444) return 34;
if (lat < 56.59318756) return 33;
if (lat < 57.72747354) return 32;
if (lat < 58.84763776) return 31;
if (lat < 59.95459277) return 30;
if (lat < 61.04917774) return 29;
if (lat < 62.13216659) return 28;
if (lat < 63.20427479) return 27;
if (lat < 64.26616523) return 26;
if (lat < 65.31845310) return 25;
if (lat < 66.36171008) return 24;
if (lat < 67.39646774) return 23;
if (lat < 68.42322022) return 22;
if (lat < 69.44242631) return 21;
if (lat < 70.45451075) return 20;
if (lat < 71.45986473) return 19;
if (lat < 72.45884545) return 18;
if (lat < 73.45177442) return 17;
if (lat < 74.43893416) return 16;
if (lat < 75.42056257) return 15;
if (lat < 76.39684391) return 14;
if (lat < 77.36789461) return 13;
if (lat < 78.33374083) return 12;
if (lat < 79.29428225) return 11;
if (lat < 80.24923213) return 10;
if (lat < 81.19801349) return 9;
if (lat < 82.13956981) return 8;
if (lat < 83.07199445) return 7;
if (lat < 83.99173563) return 6;
if (lat < 84.89166191) return 5;
if (lat < 85.75541621) return 4;
if (lat < 86.53536998) return 3;
if (lat < 87.00000000) return 2;
else return 1;
}
//
//=========================================================================
//
static int cprNFunction(double lat, int fflag) {
int nl = cprNLFunction(lat) - (fflag ? 1 : 0);
if (nl < 1) nl = 1;
return nl;
}
//
//=========================================================================
//
static double cprDlonFunction(double lat, int fflag, int surface) {
return (surface ? 90.0 : 360.0) / cprNFunction(lat, fflag);
}
//
//=========================================================================
//
// This algorithm comes from:
// http://www.lll.lu/~edward/edward/adsb/DecodingADSBposition.html.
//
// A few remarks:
// 1) 131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits.
//
int decodeCPRairborne(int even_cprlat, int even_cprlon,
int odd_cprlat, int odd_cprlon,
int fflag,
double *out_lat, double *out_lon)
{
double AirDlat0 = 360.0 / 60.0;
double AirDlat1 = 360.0 / 59.0;
double lat0 = even_cprlat;
double lat1 = odd_cprlat;
double lon0 = even_cprlon;
double lon1 = odd_cprlon;
double rlat, rlon;
// Compute the Latitude Index "j"
int j = (int) floor(((59*lat0 - 60*lat1) / 131072) + 0.5);
double rlat0 = AirDlat0 * (cprModInt(j,60) + lat0 / 131072);
double rlat1 = AirDlat1 * (cprModInt(j,59) + lat1 / 131072);
if (rlat0 >= 270) rlat0 -= 360;
if (rlat1 >= 270) rlat1 -= 360;
// Check to see that the latitude is in range: -90 .. +90
if (rlat0 < -90 || rlat0 > 90 || rlat1 < -90 || rlat1 > 90)
return (-2); // bad data
// Check that both are in the same latitude zone, or abort.
if (cprNLFunction(rlat0) != cprNLFunction(rlat1))
return (-1); // positions crossed a latitude zone, try again later
// Compute ni and the Longitude Index "m"
if (fflag) { // Use odd packet.
int ni = cprNFunction(rlat1,1);
int m = (int) floor((((lon0 * (cprNLFunction(rlat1)-1)) -
(lon1 * cprNLFunction(rlat1))) / 131072.0) + 0.5);
rlon = cprDlonFunction(rlat1, 1, 0) * (cprModInt(m, ni)+lon1/131072);
rlat = rlat1;
} else { // Use even packet.
int ni = cprNFunction(rlat0,0);
int m = (int) floor((((lon0 * (cprNLFunction(rlat0)-1)) -
(lon1 * cprNLFunction(rlat0))) / 131072) + 0.5);
rlon = cprDlonFunction(rlat0, 0, 0) * (cprModInt(m, ni)+lon0/131072);
rlat = rlat0;
}
// Renormalize to -180 .. +180
rlon -= floor( (rlon + 180) / 360 ) * 360;
*out_lat = rlat;
*out_lon = rlon;
return 0;
}
int decodeCPRsurface(double reflat, double reflon,
int even_cprlat, int even_cprlon,
int odd_cprlat, int odd_cprlon,
int fflag,
double *out_lat, double *out_lon)
{
double AirDlat0 = 90.0 / 60.0;
double AirDlat1 = 90.0 / 59.0;
double lat0 = even_cprlat;
double lat1 = odd_cprlat;
double lon0 = even_cprlon;
double lon1 = odd_cprlon;
double rlon, rlat;
// Compute the Latitude Index "j"
int j = (int) floor(((59*lat0 - 60*lat1) / 131072) + 0.5);
double rlat0 = AirDlat0 * (cprModInt(j,60) + lat0 / 131072);
double rlat1 = AirDlat1 * (cprModInt(j,59) + lat1 / 131072);
// Pick the quadrant that's closest to the reference location -
// this is not necessarily the same quadrant that contains the
// reference location.
//
// There are also only two valid quadrants: -90..0 and 0..90;
// no correct message would try to encoding a latitude in the
// ranges -180..-90 and 90..180.
//
// If the computed latitude is more than 45 degrees north of
// the reference latitude (using the northern hemisphere
// solution), then the southern hemisphere solution will be
// closer to the refernce latitude.
//
// e.g. reflat=0, rlat=44, use rlat=44
// reflat=0, rlat=46, use rlat=46-90 = -44
// reflat=40, rlat=84, use rlat=84
// reflat=40, rlat=86, use rlat=86-90 = -4
// reflat=-40, rlat=4, use rlat=4
// reflat=-40, rlat=6, use rlat=6-90 = -84
// As a special case, -90, 0 and +90 all encode to zero, so
// there's a little extra work to do there.
if (rlat0 == 0) {
if (reflat < -45)
rlat0 = -90;
else if (reflat > 45)
rlat0 = 90;
} else if ((rlat0 - reflat) > 45) {
rlat0 -= 90;
}
if (rlat1 == 0) {
if (reflat < -45)
rlat1 = -90;
else if (reflat > 45)
rlat1 = 90;
} else if ((rlat1 - reflat) > 45) {
rlat1 -= 90;
}
// Check to see that the latitude is in range: -90 .. +90
if (rlat0 < -90 || rlat0 > 90 || rlat1 < -90 || rlat1 > 90)
return (-2); // bad data
// Check that both are in the same latitude zone, or abort.
if (cprNLFunction(rlat0) != cprNLFunction(rlat1))
return (-1); // positions crossed a latitude zone, try again later
// Compute ni and the Longitude Index "m"
if (fflag) { // Use odd packet.
int ni = cprNFunction(rlat1,1);
int m = (int) floor((((lon0 * (cprNLFunction(rlat1)-1)) -
(lon1 * cprNLFunction(rlat1))) / 131072.0) + 0.5);
rlon = cprDlonFunction(rlat1, 1, 1) * (cprModInt(m, ni)+lon1/131072);
rlat = rlat1;
} else { // Use even packet.
int ni = cprNFunction(rlat0,0);
int m = (int) floor((((lon0 * (cprNLFunction(rlat0)-1)) -
(lon1 * cprNLFunction(rlat0))) / 131072) + 0.5);
rlon = cprDlonFunction(rlat0, 0, 1) * (cprModInt(m, ni)+lon0/131072);
rlat = rlat0;
}
// Pick the quadrant that's closest to the reference location -
// this is not necessarily the same quadrant that contains the
// reference location. Unlike the latitude case, all four
// quadrants are valid.
// if reflon is more than 45 degrees away, move some multiple of 90 degrees towards it
rlon += floor( (reflon - rlon + 45) / 90 ) * 90; // this might move us outside (-180..+180), we fix this below
// Renormalize to -180 .. +180
rlon -= floor( (rlon + 180) / 360 ) * 360;
*out_lat = rlat;
*out_lon = rlon;
return 0;
}
//
//=========================================================================
//
// This algorithm comes from:
// 1090-WP29-07-Draft_CPR101 (which also defines decodeCPR() )
//
// Despite what the earlier comment here said, we should *not* be using trunc().
// See Figure 5-5 / 5-6 and note that floor is applied to (0.5 + fRP - fEP), not
// directly to (fRP - fEP). Eq 38 is correct.
//
int decodeCPRrelative(double reflat, double reflon,
int cprlat, int cprlon,
int fflag, int surface,
double *out_lat, double *out_lon)
{
double AirDlat;
double AirDlon;
double fractional_lat = cprlat / 131072.0;
double fractional_lon = cprlon / 131072.0;
double rlon, rlat;
int j,m;
AirDlat = (surface ? 90.0 : 360.0) / (fflag ? 59.0 : 60.0);
// Compute the Latitude Index "j"
j = (int) (floor(reflat/AirDlat) +
floor(0.5 + cprModDouble(reflat, AirDlat)/AirDlat - fractional_lat));
rlat = AirDlat * (j + fractional_lat);
if (rlat >= 270) rlat -= 360;
// Check to see that the latitude is in range: -90 .. +90
if (rlat < -90 || rlat > 90) {
return (-1); // Time to give up - Latitude error
}
// Check to see that answer is reasonable - ie no more than 1/2 cell away
if (fabs(rlat - reflat) > (AirDlat/2)) {
return (-1); // Time to give up - Latitude error
}
// Compute the Longitude Index "m"
AirDlon = cprDlonFunction(rlat, fflag, surface);
m = (int) (floor(reflon/AirDlon) +
floor(0.5 + cprModDouble(reflon, AirDlon)/AirDlon - fractional_lon));
rlon = AirDlon * (m + fractional_lon);
if (rlon > 180) rlon -= 360;
// Check to see that answer is reasonable - ie no more than 1/2 cell away
if (fabs(rlon - reflon) > (AirDlon/2))
return (-1); // Time to give up - Longitude error
*out_lat = rlat;
*out_lon = rlon;
return (0);
}

39
cpr.h Normal file
View File

@ -0,0 +1,39 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// cpr.h - Compact Position Reporting prototypes
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef DUMP1090_CPR_H
#define DUMP1090_CPR_H
int decodeCPRairborne(int even_cprlat, int even_cprlon,
int odd_cprlat, int odd_cprlon,
int fflag,
double *out_lat, double *out_lon);
int decodeCPRsurface(double reflat, double reflon,
int even_cprlat, int even_cprlon,
int odd_cprlat, int odd_cprlon,
int fflag,
double *out_lat, double *out_lon);
int decodeCPRrelative(double reflat, double reflon,
int cprlat, int cprlon,
int fflag, int surface,
double *out_lat, double *out_lon);
#endif

309
cprtests.c Normal file
View File

@ -0,0 +1,309 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// cprtests.c - tests for CPR decoder
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <math.h>
#include <stdio.h>
#include "cpr.h"
// Global, airborne CPR test data:
static const struct {
int even_cprlat, even_cprlon; // input: raw CPR values, even message
int odd_cprlat, odd_cprlon; // input: raw CPR values, odd message
int even_result; // verify: expected result from decoding with fflag=0 (even message is latest)
double even_rlat, even_rlon; // verify: expected position from decoding with fflag=0 (even message is latest)
int odd_result; // verify: expected result from decoding with fflag=1 (odd message is latest)
double odd_rlat, odd_rlon; // verify: expected position from decoding with fflag=1 (odd message is latest)
} cprGlobalAirborneTests[] = {
{ 80536, 9432, 61720, 9192, 0, 51.686646, 0.700156, 0, 51.686763, 0.701294 },
{ 80534, 9413, 61714, 9144, 0, 51.686554, 0.698745, 0, 51.686484, 0.697632 },
// todo: more positions, bad data
};
// Global, surface CPR test data:
static const struct {
double reflat, reflon; // input: reference location for decoding
int even_cprlat, even_cprlon; // input: raw CPR values, even message
int odd_cprlat, odd_cprlon; // input: raw CPR values, odd message
int even_result; // verify: expected result from decoding with fflag=0 (even message is latest)
double even_rlat, even_rlon; // verify: expected position from decoding with fflag=0 (even message is latest)
int odd_result; // verify: expected result from decoding with fflag=1 (odd message is latest)
double odd_rlat, odd_rlon; // verify: expected position from decoding with fflag=1 (odd message is latest)
} cprGlobalSurfaceTests[] = {
// The real position received here was on the Cambridge (UK) airport apron at 52.21N 0.177E
// We mess with the reference location to check that the right quadrant is used.
// longitude quadrants:
{ 52.00, -180.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 180.0, 0, 52.209976, 0.176507 - 180.0 },
{ 52.00, -140.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 180.0, 0, 52.209976, 0.176507 - 180.0 },
{ 52.00, -130.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 90.0, 0, 52.209976, 0.176507 - 90.0 },
{ 52.00, -50.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 90.0, 0, 52.209976, 0.176507 - 90.0 },
{ 52.00, -40.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, -10.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, 10.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, 40.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, 50.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 + 90.0, 0, 52.209976, 0.176507 + 90.0 },
{ 52.00, 130.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 + 90.0, 0, 52.209976, 0.176507 + 90.0 },
{ 52.00, 140.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 180.0, 0, 52.209976, 0.176507 - 180.0 },
{ 52.00, 180.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601 - 180.0, 0, 52.209976, 0.176507 - 180.0 },
// latitude quadrants (but only 2). The decoded longitude also changes because the cell size changes with latitude
{ 90.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 52.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 8.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984, 0.176601, 0, 52.209976, 0.176507 },
{ 7.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984 - 90.0, 0.135269, 0, 52.209976 - 90.0, 0.134299 },
{ -52.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984 - 90.0, 0.135269, 0, 52.209976 - 90.0, 0.134299 },
{ -90.00, 0.00, 105730, 9259, 29693, 8997, 0, 52.209984 - 90.0, 0.135269, 0, 52.209976 - 90.0, 0.134299 },
// poles/equator cases
{ -46.00, -180.00, 0, 0, 0, 0, 0, -90.0, -180.000000, 0, -90.0, -180.0 }, // south pole
{ -44.00, -180.00, 0, 0, 0, 0, 0, 0.0, -180.000000, 0, 0.0, -180.0 }, // equator
{ 44.00, -180.00, 0, 0, 0, 0, 0, 0.0, -180.000000, 0, 0.0, -180.0 }, // equator
{ 46.00, -180.00, 0, 0, 0, 0, 0, 90.0, -180.000000, 0, 90.0, -180.0 }, // north pole
};
// Relative CPR test data:
static const struct {
double reflat, reflon; // input: reference location for decoding
int cprlat, cprlon; // input: raw CPR values, even or odd message
int fflag; // input: fflag in raw message
int surface; // input: decode as air (0) or surface (1) position
int result; // verify: expected result
double rlat, rlon; // verify: expected position
} cprRelativeTests[] = {
//
// AIRBORNE
//
{ 52.00, 0.00, 80536, 9432, 0, 0, 0, 51.686646, 0.700156 }, // even, airborne
{ 52.00, 0.00, 61720, 9192, 1, 0, 0, 51.686763, 0.701294 }, // odd, airborne
{ 52.00, 0.00, 80534, 9413, 0, 0, 0, 51.686554, 0.698745 }, // even, airborne
{ 52.00, 0.00, 61714, 9144, 1, 0, 0, 51.686484, 0.697632 }, // odd, airborne
// test moving the receiver around a bit
// We cannot move it more than 1/2 cell away before ambiguity happens.
// latitude must be within about 3 degrees (cell size is 360/60 = 6 degrees)
{ 48.70, 0.00, 80536, 9432, 0, 0, 0, 51.686646, 0.700156 }, // even, airborne
{ 48.70, 0.00, 61720, 9192, 1, 0, 0, 51.686763, 0.701294 }, // odd, airborne
{ 48.70, 0.00, 80534, 9413, 0, 0, 0, 51.686554, 0.698745 }, // even, airborne
{ 48.70, 0.00, 61714, 9144, 1, 0, 0, 51.686484, 0.697632 }, // odd, airborne
{ 54.60, 0.00, 80536, 9432, 0, 0, 0, 51.686646, 0.700156 }, // even, airborne
{ 54.60, 0.00, 61720, 9192, 1, 0, 0, 51.686763, 0.701294 }, // odd, airborne
{ 54.60, 0.00, 80534, 9413, 0, 0, 0, 51.686554, 0.698745 }, // even, airborne
{ 54.60, 0.00, 61714, 9144, 1, 0, 0, 51.686484, 0.697632 }, // odd, airborne
// longitude must be within about 4.8 degrees at this latitude
{ 52.00, 5.40, 80536, 9432, 0, 0, 0, 51.686646, 0.700156 }, // even, airborne
{ 52.00, 5.40, 61720, 9192, 1, 0, 0, 51.686763, 0.701294 }, // odd, airborne
{ 52.00, 5.40, 80534, 9413, 0, 0, 0, 51.686554, 0.698745 }, // even, airborne
{ 52.00, 5.40, 61714, 9144, 1, 0, 0, 51.686484, 0.697632 }, // odd, airborne
{ 52.00, -4.10, 80536, 9432, 0, 0, 0, 51.686646, 0.700156 }, // even, airborne
{ 52.00, -4.10, 61720, 9192, 1, 0, 0, 51.686763, 0.701294 }, // odd, airborne
{ 52.00, -4.10, 80534, 9413, 0, 0, 0, 51.686554, 0.698745 }, // even, airborne
{ 52.00, -4.10, 61714, 9144, 1, 0, 0, 51.686484, 0.697632 }, // odd, airborne
//
// SURFACE
//
// Surface position on the Cambridge (UK) airport apron at 52.21N 0.18E
{ 52.00, 0.00, 105730, 9259, 0, 1, 0, 52.209984, 0.176601 }, // even, surface
{ 52.00, 0.00, 29693, 8997, 1, 1, 0, 52.209976, 0.176507 }, // odd, surface
// test moving the receiver around a bit
// We cannot move it more than 1/2 cell away before ambiguity happens.
// latitude must be within about 0.75 degrees (cell size is 90/60 = 1.5 degrees)
{ 51.46, 0.00, 105730, 9259, 0, 1, 0, 52.209984, 0.176601 }, // even, surface
{ 51.46, 0.00, 29693, 8997, 1, 1, 0, 52.209976, 0.176507 }, // odd, surface
{ 52.95, 0.00, 105730, 9259, 0, 1, 0, 52.209984, 0.176601 }, // even, surface
{ 52.95, 0.00, 29693, 8997, 1, 1, 0, 52.209976, 0.176507 }, // odd, surface
// longitude must be within about 1.25 degrees at this latitude
{ 52.00, 1.40, 105730, 9259, 0, 1, 0, 52.209984, 0.176601 }, // even, surface
{ 52.00, 1.40, 29693, 8997, 1, 1, 0, 52.209976, 0.176507 }, // odd, surface
{ 52.00, -1.05, 105730, 9259, 0, 1, 0, 52.209984, 0.176601 }, // even, surface
{ 52.00, -1.05, 29693, 8997, 1, 1, 0, 52.209976, 0.176507 }, // odd, surface
};
static int testCPRGlobalAirborne() {
int ok = 1;
unsigned i;
for (i = 0; i < sizeof(cprGlobalAirborneTests)/sizeof(cprGlobalAirborneTests[0]); ++i) {
double rlat = 0, rlon = 0;
int res;
res = decodeCPRairborne(cprGlobalAirborneTests[i].even_cprlat, cprGlobalAirborneTests[i].even_cprlon,
cprGlobalAirborneTests[i].odd_cprlat, cprGlobalAirborneTests[i].odd_cprlon,
0,
&rlat, &rlon);
if (res != cprGlobalAirborneTests[i].even_result
|| fabs(rlat - cprGlobalAirborneTests[i].even_rlat) > 1e-6
|| fabs(rlon - cprGlobalAirborneTests[i].even_rlon) > 1e-6) {
ok = 0;
fprintf(stderr,
"testCPRGlobalAirborne[%u,EVEN]: FAIL: decodeCPRairborne(%d,%d,%d,%d,EVEN) failed:\n"
" result %d (expected %d)\n"
" lat %.6f (expected %.6f)\n"
" lon %.6f (expected %.6f)\n",
i,
cprGlobalAirborneTests[i].even_cprlat, cprGlobalAirborneTests[i].even_cprlon,
cprGlobalAirborneTests[i].odd_cprlat, cprGlobalAirborneTests[i].odd_cprlon,
res, cprGlobalAirborneTests[i].even_result,
rlat, cprGlobalAirborneTests[i].even_rlat,
rlon, cprGlobalAirborneTests[i].even_rlon);
} else {
fprintf(stderr, "testCPRGlobalAirborne[%u,EVEN]: PASS\n", i);
}
res = decodeCPRairborne(cprGlobalAirborneTests[i].even_cprlat, cprGlobalAirborneTests[i].even_cprlon,
cprGlobalAirborneTests[i].odd_cprlat, cprGlobalAirborneTests[i].odd_cprlon,
1,
&rlat, &rlon);
if (res != cprGlobalAirborneTests[i].odd_result
|| fabs(rlat - cprGlobalAirborneTests[i].odd_rlat) > 1e-6
|| fabs(rlon - cprGlobalAirborneTests[i].odd_rlon) > 1e-6) {
ok = 0;
fprintf(stderr,
"testCPRGlobalAirborne[%u,ODD]: FAIL: decodeCPRairborne(%d,%d,%d,%d,ODD) failed:\n"
" result %d (expected %d)\n"
" lat %.6f (expected %.6f)\n"
" lon %.6f (expected %.6f)\n",
i,
cprGlobalAirborneTests[i].even_cprlat, cprGlobalAirborneTests[i].even_cprlon,
cprGlobalAirborneTests[i].odd_cprlat, cprGlobalAirborneTests[i].odd_cprlon,
res, cprGlobalAirborneTests[i].odd_result,
rlat, cprGlobalAirborneTests[i].odd_rlat,
rlon, cprGlobalAirborneTests[i].odd_rlon);
} else {
fprintf(stderr, "testCPRGlobalAirborne[%u,ODD]: PASS\n", i);
}
}
return ok;
}
static int testCPRGlobalSurface() {
int ok = 1;
unsigned i;
for (i = 0; i < sizeof(cprGlobalSurfaceTests)/sizeof(cprGlobalSurfaceTests[0]); ++i) {
double rlat = 0, rlon = 0;
int res;
res = decodeCPRsurface(cprGlobalSurfaceTests[i].reflat, cprGlobalSurfaceTests[i].reflon,
cprGlobalSurfaceTests[i].even_cprlat, cprGlobalSurfaceTests[i].even_cprlon,
cprGlobalSurfaceTests[i].odd_cprlat, cprGlobalSurfaceTests[i].odd_cprlon,
0,
&rlat, &rlon);
if (res != cprGlobalSurfaceTests[i].even_result
|| fabs(rlat - cprGlobalSurfaceTests[i].even_rlat) > 1e-6
|| fabs(rlon - cprGlobalSurfaceTests[i].even_rlon) > 1e-6) {
ok = 0;
fprintf(stderr,
"testCPRGlobalSurface[%u,EVEN]: FAIL: decodeCPRsurface(%.6f,%.6f,%d,%d,%d,%d,EVEN) failed:\n"
" result %d (expected %d)\n"
" lat %.6f (expected %.6f)\n"
" lon %.6f (expected %.6f)\n",
i,
cprGlobalSurfaceTests[i].reflat, cprGlobalSurfaceTests[i].reflon,
cprGlobalSurfaceTests[i].even_cprlat, cprGlobalSurfaceTests[i].even_cprlon,
cprGlobalSurfaceTests[i].odd_cprlat, cprGlobalSurfaceTests[i].odd_cprlon,
res, cprGlobalSurfaceTests[i].even_result,
rlat, cprGlobalSurfaceTests[i].even_rlat,
rlon, cprGlobalSurfaceTests[i].even_rlon);
} else {
fprintf(stderr, "testCPRGlobalSurface[%u,EVEN]: PASS\n", i);
}
res = decodeCPRsurface(cprGlobalSurfaceTests[i].reflat, cprGlobalSurfaceTests[i].reflon,
cprGlobalSurfaceTests[i].even_cprlat, cprGlobalSurfaceTests[i].even_cprlon,
cprGlobalSurfaceTests[i].odd_cprlat, cprGlobalSurfaceTests[i].odd_cprlon,
1,
&rlat, &rlon);
if (res != cprGlobalSurfaceTests[i].odd_result
|| fabs(rlat - cprGlobalSurfaceTests[i].odd_rlat) > 1e-6
|| fabs(rlon - cprGlobalSurfaceTests[i].odd_rlon) > 1e-6) {
ok = 0;
fprintf(stderr,
"testCPRGlobalSurface[%u,ODD]: FAIL: decodeCPRsurface(%.6f,%.6f,%d,%d,%d,%d,ODD) failed:\n"
" result %d (expected %d)\n"
" lat %.6f (expected %.6f)\n"
" lon %.6f (expected %.6f)\n",
i,
cprGlobalSurfaceTests[i].reflat, cprGlobalSurfaceTests[i].reflon,
cprGlobalSurfaceTests[i].even_cprlat, cprGlobalSurfaceTests[i].even_cprlon,
cprGlobalSurfaceTests[i].odd_cprlat, cprGlobalSurfaceTests[i].odd_cprlon,
res, cprGlobalSurfaceTests[i].odd_result,
rlat, cprGlobalSurfaceTests[i].odd_rlat,
rlon, cprGlobalSurfaceTests[i].odd_rlon);
} else {
fprintf(stderr, "testCPRGlobalSurface[%u,ODD]: PASS\n", i);
}
}
return ok;
}
static int testCPRRelative() {
int ok = 1;
unsigned i;
for (i = 0; i < sizeof(cprRelativeTests)/sizeof(cprRelativeTests[0]); ++i) {
double rlat = 0, rlon = 0;
int res;
res = decodeCPRrelative(cprRelativeTests[i].reflat, cprRelativeTests[i].reflon,
cprRelativeTests[i].cprlat, cprRelativeTests[i].cprlon,
cprRelativeTests[i].fflag, cprRelativeTests[i].surface,
&rlat, &rlon);
if (res != cprRelativeTests[i].result
|| fabs(rlat - cprRelativeTests[i].rlat) > 1e-6
|| fabs(rlon - cprRelativeTests[i].rlon) > 1e-6) {
ok = 0;
fprintf(stderr,
"testCPRRelative[%u]: FAIL: decodeCPRrelative(%.6f,%.6f,%d,%d,%d,%d) failed:\n"
" result %d (expected %d)\n"
" lat %.6f (expected %.6f)\n"
" lon %.6f (expected %.6f)\n",
i,
cprRelativeTests[i].reflat, cprRelativeTests[i].reflon,
cprRelativeTests[i].cprlat, cprRelativeTests[i].cprlon,
cprRelativeTests[i].fflag, cprRelativeTests[i].surface,
res, cprRelativeTests[i].result,
rlat, cprRelativeTests[i].rlat,
rlon, cprRelativeTests[i].rlon);
} else {
fprintf(stderr, "testCPRRelative[%u]: PASS\n", i);
}
}
return ok;
}
int main(int __attribute__ ((unused)) argc, char __attribute__ ((unused)) **argv) {
int ok = 1;
ok = testCPRGlobalAirborne() && ok;
ok = testCPRGlobalSurface() && ok;
ok = testCPRRelative() && ok;
return ok ? 0 : 1;
}

109
cpu.c Normal file
View File

@ -0,0 +1,109 @@
#include "cpu.h"
#include <stdbool.h>
#ifdef ENABLE_CPUFEATURES
#include "cpu_features_macros.h"
#endif
//
// x86
//
#ifdef CPU_FEATURES_ARCH_X86
#include "cpuinfo_x86.h"
static X86Info *x86_info()
{
static bool valid = false;
static X86Info cache;
if (!valid) {
cache = GetX86Info();
valid = true;
}
return &cache;
}
#endif
int cpu_supports_avx(void)
{
#ifdef CPU_FEATURES_ARCH_X86
return x86_info()->features.avx;
#else
return 0;
#endif
}
int cpu_supports_avx2(void)
{
#ifdef CPU_FEATURES_ARCH_X86
return x86_info()->features.avx2;
#else
return 0;
#endif
}
//
// ARM
//
#ifdef CPU_FEATURES_ARCH_ARM
#include "cpuinfo_arm.h"
static ArmInfo *arm_info()
{
static bool valid = false;
static ArmInfo cache;
if (!valid) {
cache = GetArmInfo();
valid = true;
}
return &cache;
}
#endif
int cpu_supports_armv7_neon_vfpv4(void)
{
#ifdef CPU_FEATURES_ARCH_ARM
return arm_info()->architecture >= 7 && arm_info()->features.neon && arm_info()->features.vfpv4 && arm_info()->features.vfpd32;
#else
return 0;
#endif
}
//
// AARCH64
//
#ifdef CPU_FEATURES_ARCH_AARCH64
#include "cpuinfo_aarch64.h"
static Aarch64Info *aarch64_info()
{
static bool valid = false;
static Aarch64Info cache;
if (!valid) {
cache = GetAarch64Info();
valid = true;
}
return &cache;
}
#endif
int cpu_supports_armv8_simd(void)
{
#ifdef CPU_FEATURES_ARCH_AARCH64
return aarch64_info()->features.asimd;
#else
return 0;
#endif
}

15
cpu.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef DUMP1090_CPU_H
#define DUMP1090_CPU_H
// x86
int cpu_supports_avx(void);
int cpu_supports_avx2(void);
// ARM
int cpu_supports_armv7_neon_vfpv4(void);
// AARCH64
int cpu_supports_armv8_simd(void);
int cpu_supports_armv8_simd_sve(void);
#endif

4
cpu_features/.clang-format vendored Normal file
View File

@ -0,0 +1,4 @@
---
Language: Cpp
BasedOnStyle: Google
...

4
cpu_features/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
cmake_build/
build/
*.swp

121
cpu_features/.travis.yml vendored Normal file
View File

@ -0,0 +1,121 @@
language: c
sudo: false
cache:
timeout: 1000
directories:
- $HOME/cpu_features_archives
addons:
apt_packages:
- ninja-build
env:
global:
TOOLCHAIN=NATIVE
CMAKE_GENERATOR=Ninja
matrix:
include:
- os: linux
compiler: gcc
env:
TARGET=x86_64-linux-gnu
- os: linux
compiler: clang
env:
TARGET=x86_64-linux-gnu
- os: osx
compiler: gcc
env:
TARGET=x86_64-osx
CMAKE_GENERATOR="Unix Makefiles"
- os: osx
compiler: clang
env:
TARGET=x86_64-osx
CMAKE_GENERATOR="Unix Makefiles"
- os: windows
env:
TARGET=x86_64-windows
CMAKE_GENERATOR="Visual Studio 15 2017 Win64"
# see: https://docs.travis-ci.com/user/multi-cpu-architectures/
- os: linux
arch: ppc64le
compiler: gcc
env:
TARGET=ppc64le-linux-gnu
- os: linux
arch: ppc64le
compiler: clang
env:
TARGET=ppc64le-linux-gnu
# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=aarch64-linux-gnu
QEMU_ARCH=aarch64
# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=arm-linux-gnueabihf
QEMU_ARCH=arm
# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=armv8l-linux-gnueabihf
QEMU_ARCH=arm
# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=arm-linux-gnueabi
QEMU_ARCH=arm
# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=aarch64_be-linux-gnu
QEMU_ARCH=DISABLED
# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=armeb-linux-gnueabihf
QEMU_ARCH=DISABLED
# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
- os: linux
env:
TOOLCHAIN=LINARO
TARGET=armeb-linux-gnueabi
QEMU_ARCH=DISABLED
- os: linux
env:
TOOLCHAIN=CODESCAPE
TARGET=mips32
QEMU_ARCH=mips
- os: linux
env:
TOOLCHAIN=CODESCAPE
TARGET=mips32el
QEMU_ARCH=mipsel
- os: linux
env:
TOOLCHAIN=CODESCAPE
TARGET=mips64
QEMU_ARCH=mips64
- os: linux
env:
TOOLCHAIN=CODESCAPE
TARGET=mips64el
QEMU_ARCH=mips64el
script:
- cmake --version
- bash -e -x ./scripts/run_integration.sh

259
cpu_features/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,259 @@
cmake_minimum_required(VERSION 3.0)
# option() honors normal variables.
# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
project(CpuFeatures VERSION 0.6.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
# Default Build Type to be Release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE)
endif(NOT CMAKE_BUILD_TYPE)
# BUILD_TESTING is a standard CMake variable, but we declare it here to make it
# prominent in the GUI.
option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
# it prominent in the GUI.
# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
# Prefer static linking from source whenever possible.
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
# PIC
option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC
# Force PIC on unix when building shared libs
# see: https://en.wikipedia.org/wiki/Position-independent_code
if(BUILD_SHARED_LIBS AND UNIX)
set(BUILD_PIC ON)
endif()
include(CheckIncludeFile)
include(CheckSymbolExists)
include(GNUInstallDirs)
macro(setup_include_and_definitions TARGET_NAME)
target_include_directories(${TARGET_NAME}
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/internal>
)
target_compile_definitions(${TARGET_NAME}
PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024
)
endmacro()
set(PROCESSOR_IS_MIPS FALSE)
set(PROCESSOR_IS_ARM FALSE)
set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(PROCESSOR_IS_ARM TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
set(PROCESSOR_IS_AARCH64 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)")
set(PROCESSOR_IS_X86 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h)
if(PROCESSOR_IS_MIPS)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_mips.c)
elseif(PROCESSOR_IS_ARM)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_arm.c)
elseif(PROCESSOR_IS_AARCH64)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_aarch64.c)
elseif(PROCESSOR_IS_X86)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_x86.c)
elseif(PROCESSOR_IS_POWER)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_ppc.c)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
endmacro()
#
# library : utils
#
add_library(utils OBJECT
${PROJECT_SOURCE_DIR}/include/internal/bit_utils.h
${PROJECT_SOURCE_DIR}/include/internal/filesystem.h
${PROJECT_SOURCE_DIR}/include/internal/stack_line_reader.h
${PROJECT_SOURCE_DIR}/include/internal/string_view.h
${PROJECT_SOURCE_DIR}/src/filesystem.c
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
${PROJECT_SOURCE_DIR}/src/string_view.c
)
set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
setup_include_and_definitions(utils)
#
# library : unix_based_hardware_detection
#
if(UNIX)
add_library(unix_based_hardware_detection OBJECT
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
${PROJECT_SOURCE_DIR}/src/hwcaps.c
)
setup_include_and_definitions(unix_based_hardware_detection)
check_include_file(dlfcn.h HAVE_DLFCN_H)
if(HAVE_DLFCN_H)
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H)
endif()
check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL)
if(HAVE_STRONG_GETAUXVAL)
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
endif()
set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
endif()
#
# library : cpu_features
#
set (CPU_FEATURES_HDRS)
set (CPU_FEATURES_SRCS)
add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS)
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:utils>)
if(NOT PROCESSOR_IS_X86 AND UNIX)
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:unix_based_hardware_detection>)
endif()
add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS})
set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}")
setup_include_and_definitions(cpu_features)
target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
target_include_directories(cpu_features
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
)
if(PROCESSOR_IS_X86)
if(APPLE)
target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
endif()
endif()
add_library(CpuFeature::cpu_features ALIAS cpu_features)
#
# program : list_cpu_features
#
add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c)
target_link_libraries(list_cpu_features PRIVATE cpu_features)
add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features)
#
# ndk_compat
#
if(ANDROID)
add_subdirectory(ndk_compat)
endif()
#
# tests
#
include(CTest)
if(BUILD_TESTING)
# Automatically incorporate googletest into the CMake Project if target not
# found.
enable_language(CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
if(NOT TARGET gtest OR NOT TARGET gmock_main)
# Download and unpack googletest at configure time.
configure_file(
cmake/googletest.CMakeLists.txt.in
googletest-download/CMakeLists.txt
)
execute_process(
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(
COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker settings on
# Windows.
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines the gtest and
# gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
endif()
add_subdirectory(test)
endif()
#
# Install cpu_features and list_cpu_features
#
include(GNUInstallDirs)
install(TARGETS cpu_features list_cpu_features
EXPORT CpuFeaturesTargets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(EXPORT CpuFeaturesTargets
NAMESPACE CpuFeatures::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures
COMPONENT Devel
)
include(CMakePackageConfigHelpers)
configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in
"${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
"${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
COMPONENT Devel
)

23
cpu_features/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,23 @@
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Contributor License Agreement
Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Code reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.

230
cpu_features/LICENSE vendored Normal file
View File

@ -0,0 +1,230 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--------------------------------------------------------------------------------
For files in the `ndk_compat` folder:
--------------------------------------------------------------------------------
Copyright (C) 2010 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

199
cpu_features/README.md vendored Normal file
View File

@ -0,0 +1,199 @@
# cpu_features [![Build Status](https://travis-ci.org/google/cpu_features.svg?branch=master)](https://travis-ci.org/google/cpu_features) [![Build status](https://ci.appveyor.com/api/projects/status/46d1owsj7n8dsylq/branch/master?svg=true)](https://ci.appveyor.com/project/gchatelet/cpu-features/branch/master)
A cross-platform C library to retrieve CPU features (such as available
instructions) at runtime.
## Table of Contents
- [Design Rationale](#rationale)
- [Code samples](#codesample)
- [Running sample code](#usagesample)
- [What's supported](#support)
- [Android NDK's drop in replacement](#ndk)
- [License](#license)
- [Build with cmake](#cmake)
<a name="rationale"></a>
## Design Rationale
- **Simple to use.** See the snippets below for examples.
- **Extensible.** Easy to add missing features or architectures.
- **Compatible with old compilers** and available on many architectures so it
can be used widely. To ensure that cpu_features works on as many platforms
as possible, we implemented it in a highly portable version of C: C99.
- **Sandbox-compatible.** The library uses a variety of strategies to cope
with sandboxed environments or when `cpuid` is unavailable. This is useful
when running integration tests in hermetic environments.
- **Thread safe, no memory allocation, and raises no exceptions.**
cpu_features is suitable for implementing fundamental libc functions like
`malloc`, `memcpy`, and `memcmp`.
- **Unit tested.**
<a name="codesample"></a>
## Code samples
**Note:** For C++ code, the library functions are defined in the `CpuFeatures` namespace.
### Checking features at runtime
Here's a simple example that executes a codepath if the CPU supports both the
AES and the SSE4.2 instruction sets:
```c
#include "cpuinfo_x86.h"
// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
void Compute(void) {
if (features.aes && features.sse4_2) {
// Run optimized code.
} else {
// Run standard code.
}
}
```
### Caching for faster evaluation of complex checks
If you wish, you can read all the features at once into a global variable, and
then query for the specific features you care about. Below, we store all the ARM
features and then check whether AES and NEON are supported.
```c
#include <stdbool.h>
#include "cpuinfo_arm.h"
// For C++, add `using namespace CpuFeatures;`
static const ArmFeatures features = GetArmInfo().features;
static const bool has_aes_and_neon = features.aes && features.neon;
// use has_aes_and_neon.
```
This is a good approach to take if you're checking for combinations of features
when using a compiler that is slow to extract individual bits from bit-packed
structures.
### Checking compile time flags
The following code determines whether the compiler was told to use the AVX
instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
```c
#include <stdbool.h>
#include "cpuinfo_x86.h"
// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
// use has_avx.
```
`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to
use AVX and 0 otherwise, combining compile time and runtime knowledge.
### Rejecting poor hardware implementations based on microarchitecture
On x86, the first incarnation of a feature in a microarchitecture might not be
the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve
the underlying microarchitecture so you can decide whether to use it.
Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction
set&mdash;but only if it's not Sandy Bridge.
```c
#include <stdbool.h>
#include "cpuinfo_x86.h"
// For C++, add `using namespace CpuFeatures;`
static const X86Info info = GetX86Info();
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
// use has_fast_avx.
```
This feature is currently available only for x86 microarchitectures.
<a name="usagesample"></a>
### Running sample code
Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
```shell
% ./build/list_cpu_features
arch : x86
brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz
family : 6 (0x06)
model : 45 (0x2D)
stepping : 7 (0x07)
uarch : INTEL_SNB
flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
```
```shell
% ./build/list_cpu_features --json
{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
```
<a name="support"></a>
## What's supported
| | x86³ | ARM | AArch64 | MIPS⁴ | POWER |
|---------|:----:|:-------:|:-------:|:------:|:-------:|
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A |
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ |
| MacOs | yes² | N/A | not yet | N/A | no |
| Windows | yes² | not yet | not yet | N/A | N/A |
1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
+ from glibc's
[getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html)
+ by parsing `/proc/self/auxv`
+ by parsing `/proc/cpuinfo`
2. **Features revealed from CPU.** features are retrieved by using the `cpuid`
instruction.
3. **Microarchitecture detection.** On x86 some features are not always
implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the
microarchitecture allows the client to reject particular microarchitectures.
4. All flavors of Mips are supported, little and big endian as well as 32/64
bits.
<a name="ndk"></a>
## Android NDK's drop in replacement
[cpu_features](https://github.com/google/cpu_features) is now officially
supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h)
, see [ndk_compat](ndk_compat) folder for details.
<a name="license"></a>
## License
The cpu_features library is licensed under the terms of the Apache license.
See [LICENSE](LICENSE) for more information.
<a name="cmake"></a>
## Build with CMake
Please check the [CMake build instructions](cmake/README.md).
<a name="quickstart"></a>
### Quickstart with `Ninja`
- build `list_cpu_features`
```
cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release
ninja -C/tmp/cpu_features
/tmp/cpu_features/list_cpu_features --json
```
- run tests
```
cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON
ninja -C/tmp/cpu_features
ninja -C/tmp/cpu_features test
```

7
cpu_features/WORKSPACE vendored Normal file
View File

@ -0,0 +1,7 @@
# ===== googletest =====
git_repository(
name = "com_google_googletest",
remote = "https://github.com/google/googletest.git",
commit = "c3f65335b79f47b05629e79a54685d899bc53b93",
)

24
cpu_features/appveyor.yml vendored Normal file
View File

@ -0,0 +1,24 @@
version: '{build}'
shallow_clone: true
platform: x64
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_GENERATOR: "Visual Studio 15 2017 Win64"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMAKE_GENERATOR: "Visual Studio 14 2015 Win64"
matrix:
fast_finish: true
before_build:
- cmake --version
- cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -H. -Bcmake_build -G "%CMAKE_GENERATOR%"
build_script:
- cmake --build cmake_build --config Debug --target ALL_BUILD
test_script:
- cmake --build cmake_build --config Debug --target RUN_TESTS

View File

@ -0,0 +1,3 @@
# CpuFeatures CMake configuration file
include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake")

View File

@ -0,0 +1,3 @@
# CpuFeaturesNdkCompat CMake configuration file
include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesNdkCompatTargets.cmake")

28
cpu_features/cmake/README.md vendored Normal file
View File

@ -0,0 +1,28 @@
# CMake build instructions
## Recommended usage : Incorporating cpu_features into a CMake project
For API / ABI compatibility reasons, it is recommended to build and use
cpu_features in a subdirectory of your project or as an embedded dependency.
This is similar to the recommended usage of the googletest framework
( https://github.com/google/googletest/blob/master/googletest/README.md )
Build and use step-by-step
1- Download cpu_features and copy it in a sub-directory in your project.
or add cpu_features as a git-submodule in your project
2- You can then use the cmake command `add_subdirectory()` to include
cpu_features directly and use the `cpu_features` target in your project.
3- Add the `cpu_features` target to the `target_link_libraries()` section of
your executable or of your library.
## Enabling tests
CMake default options for cpu_features is Release built type with tests
disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`,
[.travis.yml](../.travis.yml) and [appveyor.yml](../appveyor.yml) have up to
date examples.

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -0,0 +1,54 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef enum {
CPU_FEATURE_CACHE_NULL = 0,
CPU_FEATURE_CACHE_DATA = 1,
CPU_FEATURE_CACHE_INSTRUCTION = 2,
CPU_FEATURE_CACHE_UNIFIED = 3,
CPU_FEATURE_CACHE_TLB = 4,
CPU_FEATURE_CACHE_DTLB = 5,
CPU_FEATURE_CACHE_STLB = 6,
CPU_FEATURE_CACHE_PREFETCH = 7
} CacheType;
typedef struct {
int level;
CacheType cache_type;
int cache_size; // Cache size in bytes
int ways; // Associativity, 0 undefined, 0xFF fully associative
int line_size; // Cache line size in bytes
int tlb_entries; // number of entries for TLB
int partitioning; // number of lines per sector
} CacheLevelInfo;
// Increase this value if more cache levels are needed.
#ifndef CPU_FEATURES_MAX_CACHE_LEVEL
#define CPU_FEATURES_MAX_CACHE_LEVEL 10
#endif
typedef struct {
int size;
CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL];
} CacheInfo;
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_

View File

@ -0,0 +1,216 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
////////////////////////////////////////////////////////////////////////////////
// Architectures
////////////////////////////////////////////////////////////////////////////////
#if defined(__pnacl__) || defined(__CLR_VER)
#define CPU_FEATURES_ARCH_VM
#endif
#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM)
#define CPU_FEATURES_ARCH_X86_32
#endif
#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM)
#define CPU_FEATURES_ARCH_X86_64
#endif
#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64)
#define CPU_FEATURES_ARCH_X86
#endif
#if (defined(__arm__) || defined(_M_ARM))
#define CPU_FEATURES_ARCH_ARM
#endif
#if defined(__aarch64__)
#define CPU_FEATURES_ARCH_AARCH64
#endif
#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM))
#define CPU_FEATURES_ARCH_ANY_ARM
#endif
#if defined(__mips64)
#define CPU_FEATURES_ARCH_MIPS64
#endif
#if defined(__mips__) && !defined(__mips64) // mips64 also declares __mips__
#define CPU_FEATURES_ARCH_MIPS32
#endif
#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64)
#define CPU_FEATURES_ARCH_MIPS
#endif
#if defined(__powerpc__)
#define CPU_FEATURES_ARCH_PPC
#endif
////////////////////////////////////////////////////////////////////////////////
// Os
////////////////////////////////////////////////////////////////////////////////
#if defined(__linux__)
#define CPU_FEATURES_OS_LINUX_OR_ANDROID
#endif
#if defined(__ANDROID__)
#define CPU_FEATURES_OS_ANDROID
#endif
#if (defined(_WIN64) || defined(_WIN32))
#define CPU_FEATURES_OS_WINDOWS
#endif
#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
#define CPU_FEATURES_OS_DARWIN
#endif
////////////////////////////////////////////////////////////////////////////////
// Compilers
////////////////////////////////////////////////////////////////////////////////
#if defined(__clang__)
#define CPU_FEATURES_COMPILER_CLANG
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define CPU_FEATURES_COMPILER_GCC
#endif
#if defined(_MSC_VER)
#define CPU_FEATURES_COMPILER_MSC
#endif
////////////////////////////////////////////////////////////////////////////////
// Cpp
////////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
#define CPU_FEATURES_START_CPP_NAMESPACE \
namespace cpu_features { \
extern "C" {
#define CPU_FEATURES_END_CPP_NAMESPACE \
} \
}
#else
#define CPU_FEATURES_START_CPP_NAMESPACE
#define CPU_FEATURES_END_CPP_NAMESPACE
#endif
////////////////////////////////////////////////////////////////////////////////
// Compiler flags
////////////////////////////////////////////////////////////////////////////////
// Use the following to check if a feature is known to be available at
// compile time. See README.md for an example.
#if defined(CPU_FEATURES_ARCH_X86)
#if defined(__AES__)
#define CPU_FEATURES_COMPILED_X86_AES 1
#else
#define CPU_FEATURES_COMPILED_X86_AES 0
#endif // defined(__AES__)
#if defined(__F16C__)
#define CPU_FEATURES_COMPILED_X86_F16C 1
#else
#define CPU_FEATURES_COMPILED_X86_F16C 0
#endif // defined(__F16C__)
#if defined(__BMI__)
#define CPU_FEATURES_COMPILED_X86_BMI 1
#else
#define CPU_FEATURES_COMPILED_X86_BMI 0
#endif // defined(__BMI__)
#if defined(__BMI2__)
#define CPU_FEATURES_COMPILED_X86_BMI2 1
#else
#define CPU_FEATURES_COMPILED_X86_BMI2 0
#endif // defined(__BMI2__)
#if (defined(__SSE__) || (_M_IX86_FP >= 1))
#define CPU_FEATURES_COMPILED_X86_SSE 1
#else
#define CPU_FEATURES_COMPILED_X86_SSE 0
#endif
#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
#define CPU_FEATURES_COMPILED_X86_SSE2 1
#else
#define CPU_FEATURES_COMPILED_X86_SSE2 0
#endif
#if defined(__SSE3__)
#define CPU_FEATURES_COMPILED_X86_SSE3 1
#else
#define CPU_FEATURES_COMPILED_X86_SSE3 0
#endif // defined(__SSE3__)
#if defined(__SSSE3__)
#define CPU_FEATURES_COMPILED_X86_SSSE3 1
#else
#define CPU_FEATURES_COMPILED_X86_SSSE3 0
#endif // defined(__SSSE3__)
#if defined(__SSE4_1__)
#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
#else
#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
#endif // defined(__SSE4_1__)
#if defined(__SSE4_2__)
#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
#else
#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
#endif // defined(__SSE4_2__)
#if defined(__AVX__)
#define CPU_FEATURES_COMPILED_X86_AVX 1
#else
#define CPU_FEATURES_COMPILED_X86_AVX 0
#endif // defined(__AVX__)
#if defined(__AVX2__)
#define CPU_FEATURES_COMPILED_X86_AVX2 1
#else
#define CPU_FEATURES_COMPILED_X86_AVX2 0
#endif // defined(__AVX2__)
#endif // defined(CPU_FEATURES_ARCH_X86)
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
#if defined(__ARM_NEON__)
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
#else
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
#endif // defined(__ARM_NEON__)
#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
#if defined(CPU_FEATURES_ARCH_MIPS)
#if defined(__mips_msa)
#define CPU_FEATURES_COMPILED_MIPS_MSA 1
#else
#define CPU_FEATURES_COMPILED_MIPS_MSA 0
#endif // defined(__mips_msa)
#endif // defined(CPU_FEATURES_ARCH_MIPS)
#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_

156
cpu_features/include/cpuinfo_aarch64.h vendored Normal file
View File

@ -0,0 +1,156 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
int fp : 1; // Floating-point.
int asimd : 1; // Advanced SIMD.
int evtstrm : 1; // Generic timer generated events.
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
int pmull : 1; // Polynomial multiply long.
int sha1 : 1; // Hardware-accelerated SHA1.
int sha2 : 1; // Hardware-accelerated SHA2-256.
int crc32 : 1; // Hardware-accelerated CRC-32.
int atomics : 1; // Armv8.1 atomic instructions.
int fphp : 1; // Half-precision floating point support.
int asimdhp : 1; // Advanced SIMD half-precision support.
int cpuid : 1; // Access to certain ID registers.
int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
int jscvt : 1; // Support for JavaScript conversion.
int fcma : 1; // Floating point complex numbers.
int lrcpc : 1; // Support for weaker release consistency.
int dcpop : 1; // Data persistence writeback.
int sha3 : 1; // Hardware-accelerated SHA3.
int sm3 : 1; // Hardware-accelerated SM3.
int sm4 : 1; // Hardware-accelerated SM4.
int asimddp : 1; // Dot product instruction.
int sha512 : 1; // Hardware-accelerated SHA512.
int sve : 1; // Scalable Vector Extension.
int asimdfhm : 1; // Additional half-precision instructions.
int dit : 1; // Data independent timing.
int uscat : 1; // Unaligned atomics support.
int ilrcpc : 1; // Additional support for weaker release consistency.
int flagm : 1; // Flag manipulation instructions.
int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
int sb : 1; // Speculation barrier.
int paca : 1; // Address authentication.
int pacg : 1; // Generic authentication.
int dcpodp : 1; // Data cache clean to point of persistence.
int sve2 : 1; // Scalable Vector Extension (version 2).
int sveaes : 1; // SVE AES instructions.
int svepmull : 1; // SVE polynomial multiply long instructions.
int svebitperm : 1; // SVE bit permute instructions.
int svesha3 : 1; // SVE SHA3 instructions.
int svesm4 : 1; // SVE SM4 instructions.
int flagm2 : 1; // Additional flag manipulation instructions.
int frint : 1; // Floating point to integer rounding.
int svei8mm : 1; // SVE Int8 matrix multiplication instructions.
int svef32mm : 1; // SVE FP32 matrix multiplication instruction.
int svef64mm : 1; // SVE FP64 matrix multiplication instructions.
int svebf16 : 1; // SVE BFloat16 instructions.
int i8mm : 1; // Int8 matrix multiplication instructions.
int bf16 : 1; // BFloat16 instructions.
int dgh : 1; // Data Gathering Hint instruction.
int rng : 1; // True random number generator support.
int bti : 1; // Branch target identification.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
typedef struct {
Aarch64Features features;
int implementer;
int variant;
int part;
int revision;
} Aarch64Info;
Aarch64Info GetAarch64Info(void);
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
typedef enum {
AARCH64_FP,
AARCH64_ASIMD,
AARCH64_EVTSTRM,
AARCH64_AES,
AARCH64_PMULL,
AARCH64_SHA1,
AARCH64_SHA2,
AARCH64_CRC32,
AARCH64_ATOMICS,
AARCH64_FPHP,
AARCH64_ASIMDHP,
AARCH64_CPUID,
AARCH64_ASIMDRDM,
AARCH64_JSCVT,
AARCH64_FCMA,
AARCH64_LRCPC,
AARCH64_DCPOP,
AARCH64_SHA3,
AARCH64_SM3,
AARCH64_SM4,
AARCH64_ASIMDDP,
AARCH64_SHA512,
AARCH64_SVE,
AARCH64_ASIMDFHM,
AARCH64_DIT,
AARCH64_USCAT,
AARCH64_ILRCPC,
AARCH64_FLAGM,
AARCH64_SSBS,
AARCH64_SB,
AARCH64_PACA,
AARCH64_PACG,
AARCH64_DCPODP,
AARCH64_SVE2,
AARCH64_SVEAES,
AARCH64_SVEPMULL,
AARCH64_SVEBITPERM,
AARCH64_SVESHA3,
AARCH64_SVESM4,
AARCH64_FLAGM2,
AARCH64_FRINT,
AARCH64_SVEI8MM,
AARCH64_SVEF32MM,
AARCH64_SVEF64MM,
AARCH64_SVEBF16,
AARCH64_I8MM,
AARCH64_BF16,
AARCH64_DGH,
AARCH64_RNG,
AARCH64_BTI,
AARCH64_LAST_,
} Aarch64FeaturesEnum;
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value);
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum);
CPU_FEATURES_END_CPP_NAMESPACE
#if !defined(CPU_FEATURES_ARCH_AARCH64)
#error "Including cpuinfo_aarch64.h from a non-aarch64 target."
#endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_

121
cpu_features/include/cpuinfo_arm.h vendored Normal file
View File

@ -0,0 +1,121 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
#include <stdint.h> // uint32_t
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
int swp : 1; // SWP instruction (atomic read-modify-write)
int half : 1; // Half-word loads and stores
int thumb : 1; // Thumb (16-bit instruction set)
int _26bit : 1; // "26 Bit" Model (Processor status register folded into
// program counter)
int fastmult : 1; // 32x32->64-bit multiplication
int fpa : 1; // Floating point accelerator
int vfp : 1; // Vector Floating Point.
int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all
// others above)
int java : 1; // Jazelle (Java bytecode accelerator)
int iwmmxt : 1; // Intel Wireless MMX Technology.
int crunch : 1; // MaverickCrunch coprocessor
int thumbee : 1; // ThumbEE
int neon : 1; // Advanced SIMD.
int vfpv3 : 1; // VFP version 3
int vfpv3d16 : 1; // VFP version 3 with 16 D-registers
int tls : 1; // TLS register
int vfpv4 : 1; // VFP version 4 with fast context switching
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
int vfpd32 : 1; // VFP with 32 D-registers
int lpae : 1; // Large Physical Address Extension (>4GB physical memory on
// 32-bit architecture)
int evtstrm : 1; // kernel event stream using generic architected timer
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
int pmull : 1; // Polynomial multiply long.
int sha1 : 1; // Hardware-accelerated SHA1.
int sha2 : 1; // Hardware-accelerated SHA2-256.
int crc32 : 1; // Hardware-accelerated CRC-32.
// Make sure to update ArmFeaturesEnum below if you add a field here.
} ArmFeatures;
typedef struct {
ArmFeatures features;
int implementer;
int architecture;
int variant;
int part;
int revision;
} ArmInfo;
// TODO(user): Add macros to know which features are present at compile
// time.
ArmInfo GetArmInfo(void);
// Compute CpuId from ArmInfo.
uint32_t GetArmCpuId(const ArmInfo* const info);
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
typedef enum {
ARM_SWP,
ARM_HALF,
ARM_THUMB,
ARM_26BIT,
ARM_FASTMULT,
ARM_FPA,
ARM_VFP,
ARM_EDSP,
ARM_JAVA,
ARM_IWMMXT,
ARM_CRUNCH,
ARM_THUMBEE,
ARM_NEON,
ARM_VFPV3,
ARM_VFPV3D16,
ARM_TLS,
ARM_VFPV4,
ARM_IDIVA,
ARM_IDIVT,
ARM_VFPD32,
ARM_LPAE,
ARM_EVTSTRM,
ARM_AES,
ARM_PMULL,
ARM_SHA1,
ARM_SHA2,
ARM_CRC32,
ARM_LAST_,
} ArmFeaturesEnum;
int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value);
const char* GetArmFeaturesEnumName(ArmFeaturesEnum);
CPU_FEATURES_END_CPP_NAMESPACE
#if !defined(CPU_FEATURES_ARCH_ARM)
#error "Including cpuinfo_arm.h from a non-arm target."
#endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_

60
cpu_features/include/cpuinfo_mips.h vendored Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
int msa : 1; // MIPS SIMD Architecture
// https://www.mips.com/products/architectures/ase/simd/
int eva : 1; // Enhanced Virtual Addressing
// https://www.mips.com/products/architectures/mips64/
int r6 : 1; // True if is release 6 of the processor.
// Make sure to update MipsFeaturesEnum below if you add a field here.
} MipsFeatures;
typedef struct {
MipsFeatures features;
} MipsInfo;
MipsInfo GetMipsInfo(void);
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
typedef enum {
MIPS_MSA,
MIPS_EVA,
MIPS_R6,
MIPS_LAST_,
} MipsFeaturesEnum;
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value);
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum);
CPU_FEATURES_END_CPP_NAMESPACE
#if !defined(CPU_FEATURES_ARCH_MIPS)
#error "Including cpuinfo_mips.h from a non-mips target."
#endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_

146
cpu_features/include/cpuinfo_ppc.h vendored Normal file
View File

@ -0,0 +1,146 @@
// Copyright 2018 IBM
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
#include "internal/hwcaps.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
int ppc32 : 1;
int ppc64 : 1;
int ppc601 : 1;
int altivec : 1;
int fpu : 1;
int mmu : 1;
int mac_4xx : 1;
int unifiedcache : 1;
int spe : 1;
int efpsingle : 1;
int efpdouble : 1;
int no_tb : 1;
int power4 : 1;
int power5 : 1;
int power5plus : 1;
int cell : 1;
int booke : 1;
int smt : 1;
int icachesnoop : 1;
int arch205 : 1;
int pa6t : 1;
int dfp : 1;
int power6ext : 1;
int arch206 : 1;
int vsx : 1;
int pseries_perfmon_compat : 1;
int truele : 1;
int ppcle : 1;
int arch207 : 1;
int htm : 1;
int dscr : 1;
int ebb : 1;
int isel : 1;
int tar : 1;
int vcrypto : 1;
int htm_nosc : 1;
int arch300 : 1;
int ieee128 : 1;
int darn : 1;
int scv : 1;
int htm_no_suspend : 1;
// Make sure to update PPCFeaturesEnum below if you add a field here.
} PPCFeatures;
typedef struct {
PPCFeatures features;
} PPCInfo;
// This function is guaranteed to be malloc, memset and memcpy free.
PPCInfo GetPPCInfo(void);
typedef struct {
char platform[64]; // 0 terminated string
char model[64]; // 0 terminated string
char machine[64]; // 0 terminated string
char cpu[64]; // 0 terminated string
PlatformType type;
} PPCPlatformStrings;
PPCPlatformStrings GetPPCPlatformStrings(void);
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
typedef enum {
PPC_32, /* 32 bit mode execution */
PPC_64, /* 64 bit mode execution */
PPC_601_INSTR, /* Old POWER ISA */
PPC_HAS_ALTIVEC, /* SIMD Unit*/
PPC_HAS_FPU, /* Floating Point Unit */
PPC_HAS_MMU, /* Memory management unit */
PPC_HAS_4xxMAC,
PPC_UNIFIED_CACHE, /* Unified instruction and data cache */
PPC_HAS_SPE, /* Signal processing extention unit */
PPC_HAS_EFP_SINGLE, /* SPE single precision fpu */
PPC_HAS_EFP_DOUBLE, /* SPE double precision fpu */
PPC_NO_TB, /* No timebase */
PPC_POWER4,
PPC_POWER5,
PPC_POWER5_PLUS,
PPC_CELL, /* Cell broadband engine */
PPC_BOOKE, /* Embedded ISA */
PPC_SMT, /* Simultaneous multi-threading */
PPC_ICACHE_SNOOP,
PPC_ARCH_2_05, /* ISA 2.05 - POWER6 */
PPC_PA6T, /* PA Semi 6T core ISA */
PPC_HAS_DFP, /* Decimal floating point unit */
PPC_POWER6_EXT,
PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */
PPC_HAS_VSX, /* Vector-scalar extension */
PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance
monitoring events */
PPC_TRUE_LE,
PPC_PPC_LE,
PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */
PPC_HTM, /* Hardware Transactional Memory */
PPC_DSCR, /* Data stream control register */
PPC_EBB, /* Event base branching */
PPC_ISEL, /* Integer select instructions */
PPC_TAR, /* Target address register */
PPC_VEC_CRYPTO, /* Vector cryptography instructions */
PPC_HTM_NOSC, /* Transactions aborted when syscall made*/
PPC_ARCH_3_00, /* ISA 3.00 - POWER9 */
PPC_HAS_IEEE128, /* VSX IEEE Binary Float 128-bit */
PPC_DARN, /* Deliver a random number instruction */
PPC_SCV, /* scv syscall */
PPC_HTM_NO_SUSPEND, /* TM w/out suspended state */
PPC_LAST_,
} PPCFeaturesEnum;
int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value);
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum);
CPU_FEATURES_END_CPP_NAMESPACE
#if !defined(CPU_FEATURES_ARCH_PPC)
#error "Including cpuinfo_ppc.h from a non-ppc target."
#endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_

231
cpu_features/include/cpuinfo_x86.h vendored Normal file
View File

@ -0,0 +1,231 @@
// Copyright 2017 Google LLC
// Copyright 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features.
// The field names are based on the short name provided in the wikipedia tables.
typedef struct {
int fpu : 1;
int tsc : 1;
int cx8 : 1;
int clfsh : 1;
int mmx : 1;
int aes : 1;
int erms : 1;
int f16c : 1;
int fma4 : 1;
int fma3 : 1;
int vaes : 1;
int vpclmulqdq : 1;
int bmi1 : 1;
int hle : 1;
int bmi2 : 1;
int rtm : 1;
int rdseed : 1;
int clflushopt : 1;
int clwb : 1;
int sse : 1;
int sse2 : 1;
int sse3 : 1;
int ssse3 : 1;
int sse4_1 : 1;
int sse4_2 : 1;
int sse4a : 1;
int avx : 1;
int avx2 : 1;
int avx512f : 1;
int avx512cd : 1;
int avx512er : 1;
int avx512pf : 1;
int avx512bw : 1;
int avx512dq : 1;
int avx512vl : 1;
int avx512ifma : 1;
int avx512vbmi : 1;
int avx512vbmi2 : 1;
int avx512vnni : 1;
int avx512bitalg : 1;
int avx512vpopcntdq : 1;
int avx512_4vnniw : 1;
int avx512_4vbmi2 : 1;
int avx512_second_fma : 1;
int avx512_4fmaps : 1;
int avx512_bf16 : 1;
int avx512_vp2intersect : 1;
int amx_bf16 : 1;
int amx_tile : 1;
int amx_int8 : 1;
int pclmulqdq : 1;
int smx : 1;
int sgx : 1;
int cx16 : 1; // aka. CMPXCHG16B
int sha : 1;
int popcnt : 1;
int movbe : 1;
int rdrnd : 1;
int dca : 1;
int ss : 1;
// Make sure to update X86FeaturesEnum below if you add a field here.
} X86Features;
typedef struct {
X86Features features;
int family;
int model;
int stepping;
char vendor[13]; // 0 terminated string
} X86Info;
// Calls cpuid and returns an initialized X86info.
// This function is guaranteed to be malloc, memset and memcpy free.
X86Info GetX86Info(void);
// Returns cache hierarchy informations.
// Can call cpuid multiple times.
// Only works on Intel CPU at the moment.
// This function is guaranteed to be malloc, memset and memcpy free.
CacheInfo GetX86CacheInfo(void);
typedef enum {
X86_UNKNOWN,
INTEL_CORE, // CORE
INTEL_PNR, // PENRYN
INTEL_NHM, // NEHALEM
INTEL_ATOM_BNL, // BONNELL
INTEL_WSM, // WESTMERE
INTEL_SNB, // SANDYBRIDGE
INTEL_IVB, // IVYBRIDGE
INTEL_ATOM_SMT, // SILVERMONT
INTEL_HSW, // HASWELL
INTEL_BDW, // BROADWELL
INTEL_SKL, // SKYLAKE
INTEL_ATOM_GMT, // GOLDMONT
INTEL_KBL, // KABY LAKE
INTEL_CFL, // COFFEE LAKE
INTEL_WHL, // WHISKEY LAKE
INTEL_CNL, // CANNON LAKE
INTEL_ICL, // ICE LAKE
INTEL_TGL, // TIGER LAKE
INTEL_SPR, // SAPPHIRE RAPIDS
AMD_HAMMER, // K8
AMD_K10, // K10
AMD_BOBCAT, // K14
AMD_BULLDOZER, // K15
AMD_JAGUAR, // K16
AMD_ZEN, // K17
} X86Microarchitecture;
// Returns the underlying microarchitecture by looking at X86Info's vendor,
// family and model.
X86Microarchitecture GetX86Microarchitecture(const X86Info* info);
// Calls cpuid and fills the brand_string.
// - brand_string *must* be of size 49 (beware of array decaying).
// - brand_string will be zero terminated.
// - This function calls memcpy.
void FillX86BrandString(char brand_string[49]);
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
typedef enum {
X86_FPU,
X86_TSC,
X86_CX8,
X86_CLFSH,
X86_MMX,
X86_AES,
X86_ERMS,
X86_F16C,
X86_FMA4,
X86_FMA3,
X86_VAES,
X86_VPCLMULQDQ,
X86_BMI1,
X86_HLE,
X86_BMI2,
X86_RTM,
X86_RDSEED,
X86_CLFLUSHOPT,
X86_CLWB,
X86_SSE,
X86_SSE2,
X86_SSE3,
X86_SSSE3,
X86_SSE4_1,
X86_SSE4_2,
X86_SSE4A,
X86_AVX,
X86_AVX2,
X86_AVX512F,
X86_AVX512CD,
X86_AVX512ER,
X86_AVX512PF,
X86_AVX512BW,
X86_AVX512DQ,
X86_AVX512VL,
X86_AVX512IFMA,
X86_AVX512VBMI,
X86_AVX512VBMI2,
X86_AVX512VNNI,
X86_AVX512BITALG,
X86_AVX512VPOPCNTDQ,
X86_AVX512_4VNNIW,
X86_AVX512_4VBMI2,
X86_AVX512_SECOND_FMA,
X86_AVX512_4FMAPS,
X86_AVX512_BF16,
X86_AVX512_VP2INTERSECT,
X86_AMX_BF16,
X86_AMX_TILE,
X86_AMX_INT8,
X86_PCLMULQDQ,
X86_SMX,
X86_SGX,
X86_CX16,
X86_SHA,
X86_POPCNT,
X86_MOVBE,
X86_RDRND,
X86_DCA,
X86_SS,
X86_LAST_,
} X86FeaturesEnum;
int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value);
const char* GetX86FeaturesEnumName(X86FeaturesEnum);
const char* GetX86MicroarchitectureName(X86Microarchitecture);
CPU_FEATURES_END_CPP_NAMESPACE
#if !defined(CPU_FEATURES_ARCH_X86)
#error "Including cpuinfo_x86.h from a non-x86 target."
#endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_

View File

@ -0,0 +1,40 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
inline static bool IsBitSet(uint32_t reg, uint32_t bit) {
return (reg >> bit) & 0x1;
}
inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb,
uint32_t lsb) {
const uint64_t bits = msb - lsb + 1ULL;
const uint64_t mask = (1ULL << bits) - 1ULL;
assert(msb >= lsb);
return (reg >> lsb) & mask;
}
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_

View File

@ -0,0 +1,37 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
#include <stdint.h>
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
// A struct to hold the result of a call to cpuid.
typedef struct {
uint32_t eax, ebx, ecx, edx;
} Leaf;
// Returns the result of a call to the cpuid instruction.
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx);
// Returns the eax value of the XCR0 register.
uint32_t GetXCR0Eax(void);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_

View File

@ -0,0 +1,39 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// An interface for the filesystem that allows mocking the filesystem in
// unittests.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_
#include <stddef.h>
#include <stdint.h>
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
// Same as linux "open(filename, O_RDONLY)", retries automatically on EINTR.
int CpuFeatures_OpenFile(const char* filename);
// Same as linux "read(file_descriptor, buffer, buffer_size)", retries
// automatically on EINTR.
int CpuFeatures_ReadFile(int file_descriptor, void* buffer, size_t buffer_size);
// Same as linux "close(file_descriptor)".
void CpuFeatures_CloseFile(int file_descriptor);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_

186
cpu_features/include/internal/hwcaps.h vendored Normal file
View File

@ -0,0 +1,186 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Interface to retrieve hardware capabilities. It relies on Linux's getauxval
// or `/proc/self/auxval` under the hood.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
#include <stdbool.h>
#include <stdint.h>
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
// To avoid depending on the linux kernel we reproduce the architecture specific
// constants here.
// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
#define AARCH64_HWCAP_FP (1UL << 0)
#define AARCH64_HWCAP_ASIMD (1UL << 1)
#define AARCH64_HWCAP_EVTSTRM (1UL << 2)
#define AARCH64_HWCAP_AES (1UL << 3)
#define AARCH64_HWCAP_PMULL (1UL << 4)
#define AARCH64_HWCAP_SHA1 (1UL << 5)
#define AARCH64_HWCAP_SHA2 (1UL << 6)
#define AARCH64_HWCAP_CRC32 (1UL << 7)
#define AARCH64_HWCAP_ATOMICS (1UL << 8)
#define AARCH64_HWCAP_FPHP (1UL << 9)
#define AARCH64_HWCAP_ASIMDHP (1UL << 10)
#define AARCH64_HWCAP_CPUID (1UL << 11)
#define AARCH64_HWCAP_ASIMDRDM (1UL << 12)
#define AARCH64_HWCAP_JSCVT (1UL << 13)
#define AARCH64_HWCAP_FCMA (1UL << 14)
#define AARCH64_HWCAP_LRCPC (1UL << 15)
#define AARCH64_HWCAP_DCPOP (1UL << 16)
#define AARCH64_HWCAP_SHA3 (1UL << 17)
#define AARCH64_HWCAP_SM3 (1UL << 18)
#define AARCH64_HWCAP_SM4 (1UL << 19)
#define AARCH64_HWCAP_ASIMDDP (1UL << 20)
#define AARCH64_HWCAP_SHA512 (1UL << 21)
#define AARCH64_HWCAP_SVE (1UL << 22)
#define AARCH64_HWCAP_ASIMDFHM (1UL << 23)
#define AARCH64_HWCAP_DIT (1UL << 24)
#define AARCH64_HWCAP_USCAT (1UL << 25)
#define AARCH64_HWCAP_ILRCPC (1UL << 26)
#define AARCH64_HWCAP_FLAGM (1UL << 27)
#define AARCH64_HWCAP_SSBS (1UL << 28)
#define AARCH64_HWCAP_SB (1UL << 29)
#define AARCH64_HWCAP_PACA (1UL << 30)
#define AARCH64_HWCAP_PACG (1UL << 31)
#define AARCH64_HWCAP2_DCPODP (1UL << 0)
#define AARCH64_HWCAP2_SVE2 (1UL << 1)
#define AARCH64_HWCAP2_SVEAES (1UL << 2)
#define AARCH64_HWCAP2_SVEPMULL (1UL << 3)
#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4)
#define AARCH64_HWCAP2_SVESHA3 (1UL << 5)
#define AARCH64_HWCAP2_SVESM4 (1UL << 6)
#define AARCH64_HWCAP2_FLAGM2 (1UL << 7)
#define AARCH64_HWCAP2_FRINT (1UL << 8)
#define AARCH64_HWCAP2_SVEI8MM (1UL << 9)
#define AARCH64_HWCAP2_SVEF32MM (1UL << 10)
#define AARCH64_HWCAP2_SVEF64MM (1UL << 11)
#define AARCH64_HWCAP2_SVEBF16 (1UL << 12)
#define AARCH64_HWCAP2_I8MM (1UL << 13)
#define AARCH64_HWCAP2_BF16 (1UL << 14)
#define AARCH64_HWCAP2_DGH (1UL << 15)
#define AARCH64_HWCAP2_RNG (1UL << 16)
#define AARCH64_HWCAP2_BTI (1UL << 17)
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#define ARM_HWCAP_SWP (1UL << 0)
#define ARM_HWCAP_HALF (1UL << 1)
#define ARM_HWCAP_THUMB (1UL << 2)
#define ARM_HWCAP_26BIT (1UL << 3)
#define ARM_HWCAP_FAST_MULT (1UL << 4)
#define ARM_HWCAP_FPA (1UL << 5)
#define ARM_HWCAP_VFP (1UL << 6)
#define ARM_HWCAP_EDSP (1UL << 7)
#define ARM_HWCAP_JAVA (1UL << 8)
#define ARM_HWCAP_IWMMXT (1UL << 9)
#define ARM_HWCAP_CRUNCH (1UL << 10)
#define ARM_HWCAP_THUMBEE (1UL << 11)
#define ARM_HWCAP_NEON (1UL << 12)
#define ARM_HWCAP_VFPV3 (1UL << 13)
#define ARM_HWCAP_VFPV3D16 (1UL << 14)
#define ARM_HWCAP_TLS (1UL << 15)
#define ARM_HWCAP_VFPV4 (1UL << 16)
#define ARM_HWCAP_IDIVA (1UL << 17)
#define ARM_HWCAP_IDIVT (1UL << 18)
#define ARM_HWCAP_VFPD32 (1UL << 19)
#define ARM_HWCAP_LPAE (1UL << 20)
#define ARM_HWCAP_EVTSTRM (1UL << 21)
#define ARM_HWCAP2_AES (1UL << 0)
#define ARM_HWCAP2_PMULL (1UL << 1)
#define ARM_HWCAP2_SHA1 (1UL << 2)
#define ARM_HWCAP2_SHA2 (1UL << 3)
#define ARM_HWCAP2_CRC32 (1UL << 4)
// http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/hwcap.h
#define MIPS_HWCAP_R6 (1UL << 0)
#define MIPS_HWCAP_MSA (1UL << 1)
#define MIPS_HWCAP_CRC32 (1UL << 2)
// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h
#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H
/* in AT_HWCAP */
#define PPC_FEATURE_32 0x80000000
#define PPC_FEATURE_64 0x40000000
#define PPC_FEATURE_601_INSTR 0x20000000
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
#define PPC_FEATURE_HAS_FPU 0x08000000
#define PPC_FEATURE_HAS_MMU 0x04000000
#define PPC_FEATURE_HAS_4xxMAC 0x02000000
#define PPC_FEATURE_UNIFIED_CACHE 0x01000000
#define PPC_FEATURE_HAS_SPE 0x00800000
#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000
#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000
#define PPC_FEATURE_NO_TB 0x00100000
#define PPC_FEATURE_POWER4 0x00080000
#define PPC_FEATURE_POWER5 0x00040000
#define PPC_FEATURE_POWER5_PLUS 0x00020000
#define PPC_FEATURE_CELL 0x00010000
#define PPC_FEATURE_BOOKE 0x00008000
#define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
#define PPC_FEATURE_ARCH_2_05 0x00001000
#define PPC_FEATURE_PA6T 0x00000800
#define PPC_FEATURE_HAS_DFP 0x00000400
#define PPC_FEATURE_POWER6_EXT 0x00000200
#define PPC_FEATURE_ARCH_2_06 0x00000100
#define PPC_FEATURE_HAS_VSX 0x00000080
#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040
/* Reserved - do not use 0x00000004 */
#define PPC_FEATURE_TRUE_LE 0x00000002
#define PPC_FEATURE_PPC_LE 0x00000001
/* in AT_HWCAP2 */
#define PPC_FEATURE2_ARCH_2_07 0x80000000
#define PPC_FEATURE2_HTM 0x40000000
#define PPC_FEATURE2_DSCR 0x20000000
#define PPC_FEATURE2_EBB 0x10000000
#define PPC_FEATURE2_ISEL 0x08000000
#define PPC_FEATURE2_TAR 0x04000000
#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
#define PPC_FEATURE2_HTM_NOSC 0x01000000
#define PPC_FEATURE2_ARCH_3_00 0x00800000
#define PPC_FEATURE2_HAS_IEEE128 0x00400000
#define PPC_FEATURE2_DARN 0x00200000
#define PPC_FEATURE2_SCV 0x00100000
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
#endif
typedef struct {
unsigned long hwcaps;
unsigned long hwcaps2;
} HardwareCapabilities;
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
const HardwareCapabilities hwcaps);
typedef struct {
char platform[64]; // 0 terminated string
char base_platform[64]; // 0 terminated string
} PlatformType;
PlatformType CpuFeatures_GetPlatformType(void);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_

View File

@ -0,0 +1,49 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Reads a file line by line and stores the data on the stack. This allows
// parsing files in one go without allocating.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_
#include <stdbool.h>
#include "cpu_features_macros.h"
#include "internal/string_view.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
char buffer[STACK_LINE_READER_BUFFER_SIZE];
StringView view;
int fd;
bool skip_mode;
} StackLineReader;
// Initializes a StackLineReader.
void StackLineReader_Initialize(StackLineReader* reader, int fd);
typedef struct {
StringView line; // A view of the line.
bool eof; // Nothing more to read, we reached EOF.
bool full_line; // If false the line was truncated to
// STACK_LINE_READER_BUFFER_SIZE.
} LineResult;
// Reads the file pointed to by fd and tries to read a full line.
LineResult StackLineReader_NextLine(StackLineReader* reader);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_

View File

@ -0,0 +1,109 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A view over a piece of string. The view is not 0 terminated.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
const char* ptr;
size_t size;
} StringView;
#ifdef __cplusplus
static const StringView kEmptyStringView = {NULL, 0};
#else
static const StringView kEmptyStringView;
#endif
// Returns a StringView from the provided string.
// Passing NULL is valid only if size is 0.
static inline StringView view(const char* str, const size_t size) {
StringView view;
view.ptr = str;
view.size = size;
return view;
}
static inline StringView str(const char* str) { return view(str, strlen(str)); }
// Returns the index of the first occurrence of c in view or -1 if not found.
int CpuFeatures_StringView_IndexOfChar(const StringView view, char c);
// Returns the index of the first occurrence of sub_view in view or -1 if not
// found.
int CpuFeatures_StringView_IndexOf(const StringView view,
const StringView sub_view);
// Returns whether a is equal to b (same content).
bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b);
// Returns whether a starts with b.
bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b);
// Removes count characters from the beginning of view or kEmptyStringView if
// count if greater than view.size.
StringView CpuFeatures_StringView_PopFront(const StringView str_view,
size_t count);
// Removes count characters from the end of view or kEmptyStringView if count if
// greater than view.size.
StringView CpuFeatures_StringView_PopBack(const StringView str_view,
size_t count);
// Keeps the count first characters of view or view if count if greater than
// view.size.
StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
size_t count);
// Retrieves the first character of view. If view is empty the behavior is
// undefined.
char CpuFeatures_StringView_Front(const StringView view);
// Retrieves the last character of view. If view is empty the behavior is
// undefined.
char CpuFeatures_StringView_Back(const StringView view);
// Removes leading and tailing space characters.
StringView CpuFeatures_StringView_TrimWhitespace(StringView view);
// Convert StringView to positive integer. e.g. "42", "0x2a".
// Returns -1 on error.
int CpuFeatures_StringView_ParsePositiveNumber(const StringView view);
// Copies src StringView to dst buffer.
void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
size_t dst_size);
// Checks if line contains the specified whitespace separated word.
bool CpuFeatures_StringView_HasWord(const StringView line,
const char* const word);
// Get key/value from line. key and value are separated by ": ".
// key and value are cleaned up from leading and trailing whitespaces.
bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
StringView* key,
StringView* value);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_

60
cpu_features/ndk_compat/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,60 @@
#
# library : NDK compat
#
find_package(Threads REQUIRED)
set (NDK_COMPAT_HDRS cpu-features.h)
set (NDK_COMPAT_SRCS
cpu-features.c
$<TARGET_OBJECTS:utils>
$<TARGET_OBJECTS:unix_based_hardware_detection>
)
# Note that following `add_cpu_features_headers_and_sources` will use
# NDK_COMPAT_SRCS in lieu of NDK_COMPAT_HDRS because we don't want cpu_features
# headers to be installed alongside ndk_compat.
add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS)
add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS})
setup_include_and_definitions(ndk_compat)
target_include_directories(ndk_compat PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
include(GNUInstallDirs)
install(TARGETS ndk_compat
EXPORT CpuFeaturesNdkCompatTargets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ndk_compat
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(EXPORT CpuFeaturesNdkCompatTargets
NAMESPACE CpuFeatures::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat
COMPONENT Devel
)
include(CMakePackageConfigHelpers)
configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/CpuFeaturesNdkCompatConfig.cmake.in
"${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake"
COMPATIBILITY SameMajorVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake"
"${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat"
COMPONENT Devel
)
#
# program : NDK compat test program
#
if(ENABLE_TESTING)
add_executable(ndk-compat-test ndk-compat-test.c)
target_link_libraries(ndk-compat-test PRIVATE ndk_compat)
endif()

4
cpu_features/ndk_compat/README.md vendored Normal file
View File

@ -0,0 +1,4 @@
Provides a header compatible with [android's NDK cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h).
It is intended to be a drop in replacement for this header and help users
transition from the NDK to [Google's cpu_features library](https://github.com/google/cpu_features).

205
cpu_features/ndk_compat/cpu-features.c vendored Normal file
View File

@ -0,0 +1,205 @@
#include "cpu-features.h"
#include <pthread.h>
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
#if defined(CPU_FEATURES_ARCH_ARM)
#include "cpuinfo_arm.h"
#elif defined(CPU_FEATURES_ARCH_X86)
#include "cpuinfo_x86.h"
#elif defined(CPU_FEATURES_ARCH_MIPS)
#include "cpuinfo_mips.h"
#elif defined(CPU_FEATURES_ARCH_AARCH64)
#include "cpuinfo_aarch64.h"
#endif
static pthread_once_t g_once;
static int g_inited;
static uint64_t g_cpuFeatures;
static int g_cpuCount;
#ifdef CPU_FEATURES_ARCH_ARM
static uint32_t g_cpuIdArm;
#endif
static void set_cpu_mask_bit(uint32_t index, uint32_t* cpu_mask) {
*cpu_mask |= 1UL << index;
}
// Examples of valid inputs: "31", "4-31"
static void parse_cpu_mask(const StringView text, uint32_t* cpu_mask) {
int separator_index = CpuFeatures_StringView_IndexOfChar(text, '-');
if (separator_index < 0) { // A single cpu index
int cpu_index = CpuFeatures_StringView_ParsePositiveNumber(text);
if (cpu_index < 0) return;
set_cpu_mask_bit(cpu_index, cpu_mask);
} else {
int cpu_index_a = CpuFeatures_StringView_ParsePositiveNumber(
CpuFeatures_StringView_KeepFront(text, separator_index));
int cpu_index_b = CpuFeatures_StringView_ParsePositiveNumber(
CpuFeatures_StringView_PopFront(text, separator_index + 1));
int i;
if (cpu_index_a < 0 || cpu_index_b < 0) return;
for (i = cpu_index_a; i <= cpu_index_b; ++i) {
if (i < 32) {
set_cpu_mask_bit(i, cpu_mask);
}
}
}
}
// Format specification from
// https://www.kernel.org/doc/Documentation/cputopology.txt
// Examples of valid inputs: "31", "2,4-31,32-63", "0-1,3"
static void parse_cpu_mask_line(const LineResult result, uint32_t* cpu_mask) {
if (!result.full_line || result.eof) return;
StringView line = result.line;
for (; line.size > 0;) {
int next_entry_index = CpuFeatures_StringView_IndexOfChar(line, ',');
if (next_entry_index < 0) {
parse_cpu_mask(line, cpu_mask);
break;
}
StringView entry = CpuFeatures_StringView_KeepFront(line, next_entry_index);
parse_cpu_mask(entry, cpu_mask);
line = CpuFeatures_StringView_PopFront(line, next_entry_index + 1);
}
}
static void update_cpu_mask_from_file(const char* filename,
uint32_t* cpu_mask) {
const int fd = CpuFeatures_OpenFile(filename);
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
parse_cpu_mask_line(StackLineReader_NextLine(&reader), cpu_mask);
CpuFeatures_CloseFile(fd);
}
}
static int get_cpu_count(void) {
uint32_t cpu_mask = 0;
update_cpu_mask_from_file("/sys/devices/system/cpu/present", &cpu_mask);
update_cpu_mask_from_file("/sys/devices/system/cpu/possible", &cpu_mask);
return __builtin_popcount(cpu_mask);
}
static void android_cpuInit(void) {
g_cpuFeatures = 0;
g_cpuCount = 1;
g_inited = 1;
g_cpuCount = get_cpu_count();
if (g_cpuCount == 0) {
g_cpuCount = 1;
}
#if defined(CPU_FEATURES_ARCH_ARM)
ArmInfo info = GetArmInfo();
if (info.architecture == 7) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
if (info.features.vfpv3) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
if (info.features.neon) {
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON;
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_D32;
}
if (info.features.vfpv3d16) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FP16;
if (info.features.idiva) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
if (info.features.idivt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
if (info.features.iwmmxt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
if (info.architecture >= 6)
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
if (info.features.vfpv4) {
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA;
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
}
g_cpuIdArm = GetArmCpuId(&info);
#elif defined(CPU_FEATURES_ARCH_X86)
X86Info info = GetX86Info();
if (info.features.ssse3) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
if (info.features.popcnt) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
if (info.features.movbe) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
if (info.features.sse4_1) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1;
if (info.features.sse4_2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2;
if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI;
if (info.features.avx) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX;
if (info.features.rdrnd) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND;
if (info.features.avx2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2;
if (info.features.sha) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI;
#elif defined(CPU_FEATURES_ARCH_MIPS)
MipsInfo info = GetMipsInfo();
if (info.features.r6) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6;
if (info.features.msa) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA;
#elif defined(CPU_FEATURES_ARCH_AARCH64)
Aarch64Info info = GetAarch64Info();
if (info.features.fp) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
if (info.features.asimd) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
#endif
}
AndroidCpuFamily android_getCpuFamily(void) {
#if defined(CPU_FEATURES_ARCH_ARM)
return ANDROID_CPU_FAMILY_ARM;
#elif defined(CPU_FEATURES_ARCH_X86_32)
return ANDROID_CPU_FAMILY_X86;
#elif defined(CPU_FEATURES_ARCH_MIPS64)
return ANDROID_CPU_FAMILY_MIPS64;
#elif defined(CPU_FEATURES_ARCH_MIPS32)
return ANDROID_CPU_FAMILY_MIPS;
#elif defined(CPU_FEATURES_ARCH_AARCH64)
return ANDROID_CPU_FAMILY_ARM64;
#elif defined(CPU_FEATURES_ARCH_X86_64)
return ANDROID_CPU_FAMILY_X86_64;
#else
return ANDROID_CPU_FAMILY_UNKNOWN;
#endif
}
uint64_t android_getCpuFeatures(void) {
pthread_once(&g_once, android_cpuInit);
return g_cpuFeatures;
}
int android_getCpuCount(void) {
pthread_once(&g_once, android_cpuInit);
return g_cpuCount;
}
static void android_cpuInitDummy(void) { g_inited = 1; }
int android_setCpu(int cpu_count, uint64_t cpu_features) {
/* Fail if the library was already initialized. */
if (g_inited) return 0;
g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
g_cpuFeatures = cpu_features;
pthread_once(&g_once, android_cpuInitDummy);
return 1;
}
#ifdef CPU_FEATURES_ARCH_ARM
uint32_t android_getCpuIdArm(void) {
pthread_once(&g_once, android_cpuInit);
return g_cpuIdArm;
}
int android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) {
if (!android_setCpu(cpu_count, cpu_features)) return 0;
g_cpuIdArm = cpu_id;
return 1;
}
#endif // CPU_FEATURES_ARCH_ARM

320
cpu_features/ndk_compat/cpu-features.h vendored Normal file
View File

@ -0,0 +1,320 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef GOOGLE_CPU_FEATURES_H
#define GOOGLE_CPU_FEATURES_H
#include <stdint.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
/* A list of valid values returned by android_getCpuFamily().
* They describe the CPU Architecture of the current process.
*/
typedef enum {
ANDROID_CPU_FAMILY_UNKNOWN = 0,
ANDROID_CPU_FAMILY_ARM,
ANDROID_CPU_FAMILY_X86,
ANDROID_CPU_FAMILY_MIPS,
ANDROID_CPU_FAMILY_ARM64,
ANDROID_CPU_FAMILY_X86_64,
ANDROID_CPU_FAMILY_MIPS64,
ANDROID_CPU_FAMILY_MAX /* do not remove */
} AndroidCpuFamily;
/* Return the CPU family of the current process.
*
* Note that this matches the bitness of the current process. I.e. when
* running a 32-bit binary on a 64-bit capable CPU, this will return the
* 32-bit CPU family value.
*/
extern AndroidCpuFamily android_getCpuFamily(void);
/* Return a bitmap describing a set of optional CPU features that are
* supported by the current device's CPU. The exact bit-flags returned
* depend on the value returned by android_getCpuFamily(). See the
* documentation for the ANDROID_CPU_*_FEATURE_* flags below for details.
*/
extern uint64_t android_getCpuFeatures(void);
/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be
* recognized by the library (see note below for 64-bit ARM). Value details
* are:
*
* VFPv2:
* CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs
* support these instructions. VFPv2 is a subset of VFPv3 so this will
* be set whenever VFPv3 is set too.
*
* ARMv7:
* CPU supports the ARMv7-A basic instruction set.
* This feature is mandated by the 'armeabi-v7a' ABI.
*
* VFPv3:
* CPU supports the VFPv3-D16 instruction set, providing hardware FPU
* support for single and double precision floating point registers.
* Note that only 16 FPU registers are available by default, unless
* the D32 bit is set too. This feature is also mandated by the
* 'armeabi-v7a' ABI.
*
* VFP_D32:
* CPU VFP optional extension that provides 32 FPU registers,
* instead of 16. Note that ARM mandates this feature is the 'NEON'
* feature is implemented by the CPU.
*
* NEON:
* CPU FPU supports "ARM Advanced SIMD" instructions, also known as
* NEON. Note that this mandates the VFP_D32 feature as well, per the
* ARM Architecture specification.
*
* VFP_FP16:
* Half-width floating precision VFP extension. If set, the CPU
* supports instructions to perform floating-point operations on
* 16-bit registers. This is part of the VFPv4 specification, but
* not mandated by any Android ABI.
*
* VFP_FMA:
* Fused multiply-accumulate VFP instructions extension. Also part of
* the VFPv4 specification, but not mandated by any Android ABI.
*
* NEON_FMA:
* Fused multiply-accumulate NEON instructions extension. Optional
* extension from the VFPv4 specification, but not mandated by any
* Android ABI.
*
* IDIV_ARM:
* Integer division available in ARM mode. Only available
* on recent CPUs (e.g. Cortex-A15).
*
* IDIV_THUMB2:
* Integer division available in Thumb-2 mode. Only available
* on recent CPUs (e.g. Cortex-A15).
*
* iWMMXt:
* Optional extension that adds MMX registers and operations to an
* ARM CPU. This is only available on a few XScale-based CPU designs
* sold by Marvell. Pretty rare in practice.
*
* AES:
* CPU supports AES instructions. These instructions are only
* available for 32-bit applications running on ARMv8 CPU.
*
* CRC32:
* CPU supports CRC32 instructions. These instructions are only
* available for 32-bit applications running on ARMv8 CPU.
*
* SHA2:
* CPU supports SHA2 instructions. These instructions are only
* available for 32-bit applications running on ARMv8 CPU.
*
* SHA1:
* CPU supports SHA1 instructions. These instructions are only
* available for 32-bit applications running on ARMv8 CPU.
*
* PMULL:
* CPU supports 64-bit PMULL and PMULL2 instructions. These
* instructions are only available for 32-bit applications
* running on ARMv8 CPU.
*
* If you want to tell the compiler to generate code that targets one of
* the feature set above, you should probably use one of the following
* flags (for more details, see technical note at the end of this file):
*
* -mfpu=vfp
* -mfpu=vfpv2
* These are equivalent and tell GCC to use VFPv2 instructions for
* floating-point operations. Use this if you want your code to
* run on *some* ARMv6 devices, and any ARMv7-A device supported
* by Android.
*
* Generated code requires VFPv2 feature.
*
* -mfpu=vfpv3-d16
* Tell GCC to use VFPv3 instructions (using only 16 FPU registers).
* This should be generic code that runs on any CPU that supports the
* 'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this.
*
* Generated code requires VFPv3 feature.
*
* -mfpu=vfpv3
* Tell GCC to use VFPv3 instructions with 32 FPU registers.
* Generated code requires VFPv3|VFP_D32 features.
*
* -mfpu=neon
* Tell GCC to use VFPv3 instructions with 32 FPU registers, and
* also support NEON intrinsics (see <arm_neon.h>).
* Generated code requires VFPv3|VFP_D32|NEON features.
*
* -mfpu=vfpv4-d16
* Generated code requires VFPv3|VFP_FP16|VFP_FMA features.
*
* -mfpu=vfpv4
* Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features.
*
* -mfpu=neon-vfpv4
* Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA
* features.
*
* -mcpu=cortex-a7
* -mcpu=cortex-a15
* Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|
* NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2
* This flag implies -mfpu=neon-vfpv4.
*
* -mcpu=iwmmxt
* Allows the use of iWMMXt instrinsics with GCC.
*
* IMPORTANT NOTE: These flags should only be tested when
* android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a
* 32-bit process.
*
* When running a 64-bit ARM process on an ARMv8 CPU,
* android_getCpuFeatures() will return a different set of bitflags
*/
enum {
ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4),
ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5),
ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6),
ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7),
ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8),
ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9),
ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10),
ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11),
ANDROID_CPU_ARM_FEATURE_AES = (1 << 12),
ANDROID_CPU_ARM_FEATURE_PMULL = (1 << 13),
ANDROID_CPU_ARM_FEATURE_SHA1 = (1 << 14),
ANDROID_CPU_ARM_FEATURE_SHA2 = (1 << 15),
ANDROID_CPU_ARM_FEATURE_CRC32 = (1 << 16),
};
/* The bit flags corresponding to the output of android_getCpuFeatures()
* when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details
* are:
*
* FP:
* CPU has Floating-point unit.
*
* ASIMD:
* CPU has Advanced SIMD unit.
*
* AES:
* CPU supports AES instructions.
*
* CRC32:
* CPU supports CRC32 instructions.
*
* SHA2:
* CPU supports SHA2 instructions.
*
* SHA1:
* CPU supports SHA1 instructions.
*
* PMULL:
* CPU supports 64-bit PMULL and PMULL2 instructions.
*/
enum {
ANDROID_CPU_ARM64_FEATURE_FP = (1 << 0),
ANDROID_CPU_ARM64_FEATURE_ASIMD = (1 << 1),
ANDROID_CPU_ARM64_FEATURE_AES = (1 << 2),
ANDROID_CPU_ARM64_FEATURE_PMULL = (1 << 3),
ANDROID_CPU_ARM64_FEATURE_SHA1 = (1 << 4),
ANDROID_CPU_ARM64_FEATURE_SHA2 = (1 << 5),
ANDROID_CPU_ARM64_FEATURE_CRC32 = (1 << 6),
};
/* The bit flags corresponding to the output of android_getCpuFeatures()
* when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86 or
* ANDROID_CPU_FAMILY_X86_64.
*/
enum {
ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
ANDROID_CPU_X86_FEATURE_SSE4_1 = (1 << 3),
ANDROID_CPU_X86_FEATURE_SSE4_2 = (1 << 4),
ANDROID_CPU_X86_FEATURE_AES_NI = (1 << 5),
ANDROID_CPU_X86_FEATURE_AVX = (1 << 6),
ANDROID_CPU_X86_FEATURE_RDRAND = (1 << 7),
ANDROID_CPU_X86_FEATURE_AVX2 = (1 << 8),
ANDROID_CPU_X86_FEATURE_SHA_NI = (1 << 9),
};
/* The bit flags corresponding to the output of android_getCpuFeatures()
* when android_getCpuFamily() returns ANDROID_CPU_FAMILY_MIPS
* or ANDROID_CPU_FAMILY_MIPS64. Values are:
*
* R6:
* CPU executes MIPS Release 6 instructions natively, and
* supports obsoleted R1..R5 instructions only via kernel traps.
*
* MSA:
* CPU supports Mips SIMD Architecture instructions.
*/
enum {
ANDROID_CPU_MIPS_FEATURE_R6 = (1 << 0),
ANDROID_CPU_MIPS_FEATURE_MSA = (1 << 1),
};
/* Return the number of CPU cores detected on this device.
* Please note the current implementation supports up to 32 cpus.
*/
extern int android_getCpuCount(void);
/* The following is used to force the CPU count and features
* mask in sandboxed processes. Under 4.1 and higher, these processes
* cannot access /proc, which is the only way to get information from
* the kernel about the current hardware (at least on ARM).
*
* It _must_ be called only once, and before any android_getCpuXXX
* function, any other case will fail.
*
* This function return 1 on success, and 0 on failure.
*/
extern int android_setCpu(int cpu_count, uint64_t cpu_features);
#ifdef __arm__
/* Retrieve the ARM 32-bit CPUID value from the kernel.
* Note that this cannot work on sandboxed processes under 4.1 and
* higher, unless you called android_setCpuArm() before.
*/
extern uint32_t android_getCpuIdArm(void);
/* An ARM-specific variant of android_setCpu() that also allows you
* to set the ARM CPUID field.
*/
extern int android_setCpuArm(int cpu_count, uint64_t cpu_features,
uint32_t cpu_id);
#endif
__END_DECLS
#endif /* GOOGLE_CPU_FEATURES_H */

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include "cpu-features.h"
int main() {
printf("android_getCpuFamily()=%d\n", android_getCpuFamily());
printf("android_getCpuFeatures()=0x%08llx\n", android_getCpuFeatures());
printf("android_getCpuCount()=%d\n", android_getCpuCount());
#ifdef __arm__
printf("android_getCpuIdArm()=0x%04x\n", android_getCpuIdArm());
#endif //__arm__
}

209
cpu_features/scripts/run_integration.sh vendored Executable file
View File

@ -0,0 +1,209 @@
#!/usr/bin/env bash
readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.."
readonly ARCHIVE_FOLDER=~/cpu_features_archives
readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu
readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON"
function extract() {
case $1 in
*.tar.bz2) tar xjf "$1" ;;
*.tar.xz) tar xJf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*)
echo "don't know how to extract '$1'..."
exit 1
esac
}
function unpackifnotexists() {
mkdir -p "${ARCHIVE_FOLDER}"
cd "${ARCHIVE_FOLDER}" || exit
local URL=$1
local RELATIVE_FOLDER=$2
local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}"
if [[ ! -d "${DESTINATION}" ]] ; then
local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///')
test -f "${ARCHIVE_NAME}" || wget -q "${URL}"
extract "${ARCHIVE_NAME}"
rm -f "${ARCHIVE_NAME}"
fi
}
function installqemuifneeded() {
local VERSION=${QEMU_VERSION:=2.11.1}
local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el}
local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')}
if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then
echo "qemu ${VERSION} up to date!"
return 0
fi
echo "VERSION: ${VERSION}"
echo "TARGETS: ${TARGETS}"
rm -rf ${QEMU_INSTALL}
# Checking for a tarball before downloading makes testing easier :-)
local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz"
local QEMU_FOLDER="qemu-${VERSION}"
unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER}
cd ${QEMU_FOLDER} || exit
./configure \
--prefix="${QEMU_INSTALL}" \
--target-list="${TARGETS}" \
--disable-docs \
--disable-sdl \
--disable-gtk \
--disable-gnutls \
--disable-gcrypt \
--disable-nettle \
--disable-curses \
--static
make -j4
make install
echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build
}
function assert_defined(){
local VALUE=${1}
: "${VALUE?"${1} needs to be defined"}"
}
function integrate() {
cd "${PROJECT_FOLDER}"
case "${OS}" in
"Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD"
CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe"
DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe
;;
*) CMAKE_BUILD_ARGS="--target all"
CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test"
DEMO=${BUILD_DIR}/list_cpu_features
;;
esac
# Generating CMake configuration
cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}"
# Building
cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS}
# Running tests if needed
if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
return
fi
RUN_CMD=""
if [[ -n "${QEMU_ARCH}" ]]; then
installqemuifneeded
RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}"
fi
for test_binary in ${CMAKE_TEST_FILES}; do
${RUN_CMD} ${test_binary}
done
${RUN_CMD} ${DEMO}
}
function expand_linaro_config() {
assert_defined TARGET
local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11
local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz
local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}"
unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}"
local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz
local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET}
unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}"
local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER}
local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER}
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY)
QEMU_ARGS+=(-L ${SYSROOT_FOLDER})
QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib)
}
function expand_codescape_config() {
assert_defined TARGET
local DATE=2017.10-08
local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz
local GCC_URL=${CODESCAPE_URL}
local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}"
unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}"
local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER}
local MIPS_FLAGS=""
local LIBC_FOLDER_SUFFIX=""
local FLAVOUR=""
case "${TARGET}" in
"mips32") MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;;
"mips32el") MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;;
"mips64") MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;;
"mips64el") MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;;
*) echo 'unknown mips platform'; exit 1;;
esac
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}")
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}")
local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR}
# Keeping only the sysroot of interest to save on travis cache.
if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then
for folder in ${GCC_FOLDER}/sysroot/*; do
if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then
rm -rf ${folder}
fi
done
fi
local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX}
QEMU_ARGS+=(-L ${SYSROOT_FOLDER})
QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1)
}
function expand_environment_and_integrate() {
assert_defined PROJECT_FOLDER
assert_defined TARGET
BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}"
mkdir -p "${BUILD_DIR}"
declare -a CONFIG_NAMES=()
declare -a QEMU_ARGS=()
declare -a CMAKE_ADDITIONAL_ARGS=()
case ${TOOLCHAIN} in
LINARO) expand_linaro_config ;;
CODESCAPE) expand_codescape_config ;;
NATIVE) QEMU_ARCH="" ;;
*) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;;
esac
integrate
}
if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then
QEMU_ARCHES=${QEMU_ARCH}
expand_environment_and_integrate
fi

106
cpu_features/scripts/test_integration.sh vendored Executable file
View File

@ -0,0 +1,106 @@
#!/usr/bin/env bash
source "$(dirname -- "$0")"/run_integration.sh
# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
function set_aarch64-linux-gnu() {
TOOLCHAIN=LINARO
TARGET=aarch64-linux-gnu
QEMU_ARCH=aarch64
}
# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_arm-linux-gnueabihf() {
TOOLCHAIN=LINARO
TARGET=arm-linux-gnueabihf
QEMU_ARCH=arm
}
# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems
function set_armv8l-linux-gnueabihf() {
TOOLCHAIN=LINARO
TARGET=armv8l-linux-gnueabihf
QEMU_ARCH=arm
}
# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_arm-linux-gnueabi() {
TOOLCHAIN=LINARO
TARGET=arm-linux-gnueabi
QEMU_ARCH=arm
}
# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems
function set_aarch64_be-linux-gnu() {
TOOLCHAIN=LINARO
TARGET=aarch64_be-linux-gnu
QEMU_ARCH=DISABLED
}
# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_armeb-linux-gnueabihf() {
TOOLCHAIN=LINARO
TARGET=armeb-linux-gnueabihf
QEMU_ARCH=DISABLED
}
# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_armeb-linux-gnueabi() {
TOOLCHAIN=LINARO
TARGET=armeb-linux-gnueabi
QEMU_ARCH=DISABLED
}
function set_mips32() {
TOOLCHAIN=CODESCAPE
TARGET=mips32
QEMU_ARCH=mips
}
function set_mips32el() {
TOOLCHAIN=CODESCAPE
TARGET=mips32el
QEMU_ARCH=mipsel
}
function set_mips64() {
TOOLCHAIN=CODESCAPE
TARGET=mips64
QEMU_ARCH=mips64
}
function set_mips64el() {
TOOLCHAIN=CODESCAPE
TARGET=mips64el
QEMU_ARCH=mips64el
}
function set_native() {
TOOLCHAIN=NATIVE
TARGET=native
QEMU_ARCH=""
}
ENVIRONMENTS="
set_aarch64-linux-gnu
set_arm-linux-gnueabihf
set_armv8l-linux-gnueabihf
set_arm-linux-gnueabi
set_aarch64_be-linux-gnu
set_armeb-linux-gnueabihf
set_armeb-linux-gnueabi
set_mips32
set_mips32el
set_mips64
set_mips64el
set_native
"
set -e
CMAKE_GENERATOR="Ninja"
for SET_ENVIRONMENT in ${ENVIRONMENTS}; do
${SET_ENVIRONMENT}
expand_environment_and_integrate
done

150
cpu_features/src/cpuinfo_aarch64.c vendored Normal file
View File

@ -0,0 +1,150 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_aarch64.h"
#include <assert.h>
#include <ctype.h>
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
// Generation of feature's getters/setters functions and kGetters, kSetters,
// kCpuInfoFlags and kHardwareCapabilities global tables.
#define DEFINE_TABLE_FEATURES \
FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
AARCH64_HWCAP2_SVEBITPERM) \
FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
#include "define_tables.h"
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info) {
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
for (size_t i = 0; i < AARCH64_LAST_; ++i) {
kSetters[i](&info->features,
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
}
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
}
}
return !result.eof;
}
static void FillProcCpuInfoData(Aarch64Info* const info) {
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) {
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void) {
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
Aarch64Info info = kEmptyAarch64Info;
FillProcCpuInfoData(&info);
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
for (size_t i = 0; i < AARCH64_LAST_; ++i) {
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
kSetters[i](&info.features, true);
}
}
return info;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value) {
if (value >= AARCH64_LAST_) return false;
return kGetters[value](features);
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
if (value >= AARCH64_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

212
cpu_features/src/cpuinfo_arm.c vendored Normal file
View File

@ -0,0 +1,212 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_arm.h"
#include <assert.h>
#include <ctype.h>
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
// Generation of feature's getters/setters functions and kGetters, kSetters,
// kCpuInfoFlags and kHardwareCapabilities global tables.
#define DEFINE_TABLE_FEATURES \
FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \
FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \
FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \
FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \
FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \
FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \
FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \
FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \
FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \
FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \
FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \
FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \
FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \
FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \
FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \
FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \
FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \
FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \
FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \
FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \
FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \
FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \
FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \
FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \
FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \
FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
#include "define_tables.h"
typedef struct {
bool processor_reports_armv6;
bool hardware_reports_goldfish;
} ProcCpuInfoData;
static int IndexOfNonDigit(StringView str) {
size_t index = 0;
while (str.size && isdigit(CpuFeatures_StringView_Front(str))) {
str = CpuFeatures_StringView_PopFront(str, 1);
++index;
}
return index;
}
static bool HandleArmLine(const LineResult result, ArmInfo* const info,
ProcCpuInfoData* const proc_info) {
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
for (size_t i = 0; i < ARM_LAST_; ++i) {
kSetters[i](&info->features,
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
}
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) {
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) {
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU architecture"))) {
// CPU architecture is a number that may be followed by letters. e.g.
// "6TEJ", "7".
const StringView digits =
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
} else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) ||
CpuFeatures_StringView_IsEquals(key, str("model name"))) {
// Android reports this in a non-Linux standard "Processor" but sometimes
// also in "model name", Linux reports it only in "model name"
// see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases
proc_info->processor_reports_armv6 =
CpuFeatures_StringView_IndexOf(value, str("(v6l)")) >= 0;
} else if (CpuFeatures_StringView_IsEquals(key, str("Hardware"))) {
proc_info->hardware_reports_goldfish =
CpuFeatures_StringView_IsEquals(value, str("Goldfish"));
}
}
return !result.eof;
}
uint32_t GetArmCpuId(const ArmInfo* const info) {
return (ExtractBitRange(info->implementer, 7, 0) << 24) |
(ExtractBitRange(info->variant, 3, 0) << 20) |
(ExtractBitRange(info->part, 11, 0) << 4) |
(ExtractBitRange(info->revision, 3, 0) << 0);
}
static void FixErrors(ArmInfo* const info,
ProcCpuInfoData* const proc_cpu_info_data) {
// Fixing Samsung kernel reporting invalid cpu architecture.
// http://code.google.com/p/android/issues/detail?id=10812
if (proc_cpu_info_data->processor_reports_armv6 && info->architecture >= 7) {
info->architecture = 6;
}
// Handle kernel configuration bugs that prevent the correct reporting of CPU
// features.
switch (GetArmCpuId(info)) {
case 0x4100C080:
// Special case: The emulator-specific Android 4.2 kernel fails to report
// support for the 32-bit ARM IDIV instruction. Technically, this is a
// feature of the virtual CPU implemented by the emulator. Note that it
// could also support Thumb IDIV in the future, and this will have to be
// slightly updated.
if (info->architecture >= 7 &&
proc_cpu_info_data->hardware_reports_goldfish) {
info->features.idiva = true;
}
break;
case 0x511004D0:
// https://crbug.com/341598.
info->features.neon = false;
break;
case 0x510006F2:
case 0x510006F3:
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report
// IDIV support.
info->features.idiva = true;
info->features.idivt = true;
break;
}
// Propagate cpu features.
if (info->features.vfpv4) info->features.vfpv3 = true;
if (info->features.neon) info->features.vfpv3 = true;
if (info->features.vfpv3) info->features.vfp = true;
}
static void FillProcCpuInfoData(ArmInfo* const info,
ProcCpuInfoData* proc_cpu_info_data) {
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
if (!HandleArmLine(StackLineReader_NextLine(&reader), info,
proc_cpu_info_data)) {
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const ArmInfo kEmptyArmInfo;
static const ProcCpuInfoData kEmptyProcCpuInfoData;
ArmInfo GetArmInfo(void) {
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
ArmInfo info = kEmptyArmInfo;
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
FillProcCpuInfoData(&info, &proc_cpu_info_data);
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
for (size_t i = 0; i < ARM_LAST_; ++i) {
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
kSetters[i](&info.features, true);
}
}
FixErrors(&info, &proc_cpu_info_data);
return info;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value) {
if (value >= ARM_LAST_) return false;
return kGetters[value](features);
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
if (value >= ARM_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

92
cpu_features/src/cpuinfo_mips.c vendored Normal file
View File

@ -0,0 +1,92 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_mips.h"
#include <assert.h>
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
// Generation of feature's getters/setters functions and kGetters, kSetters,
// kCpuInfoFlags and kHardwareCapabilities global tables.
#define DEFINE_TABLE_FEATURES \
FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
FEATURE(MIPS_EVA, eva, "eva", 0, 0) \
FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
#include "define_tables.h"
static bool HandleMipsLine(const LineResult result,
MipsFeatures* const features) {
StringView key, value;
// See tests for an example.
if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) {
for (size_t i = 0; i < MIPS_LAST_; ++i) {
kSetters[i](features,
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
}
}
}
return !result.eof;
}
static void FillProcCpuInfoData(MipsFeatures* const features) {
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
if (!HandleMipsLine(StackLineReader_NextLine(&reader), features)) {
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const MipsInfo kEmptyMipsInfo;
MipsInfo GetMipsInfo(void) {
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
MipsInfo info = kEmptyMipsInfo;
FillProcCpuInfoData(&info.features);
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
for (size_t i = 0; i < MIPS_LAST_; ++i) {
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
kSetters[i](&info.features, true);
}
}
return info;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value) {
if (value >= MIPS_LAST_) return false;
return kGetters[value](features);
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
if (value >= MIPS_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

154
cpu_features/src/cpuinfo_ppc.c vendored Normal file
View File

@ -0,0 +1,154 @@
// Copyright 2018 IBM.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_ppc.h"
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
// Generation of feature's getters/setters functions and kGetters, kSetters,
// kCpuInfoFlags and kHardwareCapabilities global tables.
#define DEFINE_TABLE_FEATURES \
FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \
FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \
FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \
FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \
FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \
FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \
FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \
FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", \
PPC_FEATURE_UNIFIED_CACHE, 0) \
FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \
FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", \
PPC_FEATURE_HAS_EFP_SINGLE, 0) \
FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", \
PPC_FEATURE_HAS_EFP_DOUBLE, 0) \
FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \
FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \
FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \
FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \
FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \
FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \
FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \
FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \
0) \
FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \
FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \
FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \
FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \
FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \
FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \
FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \
PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \
FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \
FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \
FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \
FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \
FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \
FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \
FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \
FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \
FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \
FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \
FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \
FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \
FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \
FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
PPC_FEATURE2_HTM_NO_SUSPEND)
#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
#include "define_tables.h"
static bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings) {
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_HasWord(key, "platform")) {
CpuFeatures_StringView_CopyString(value, strings->platform,
sizeof(strings->platform));
} else if (CpuFeatures_StringView_IsEquals(key, str("model"))) {
CpuFeatures_StringView_CopyString(value, strings->model,
sizeof(strings->platform));
} else if (CpuFeatures_StringView_IsEquals(key, str("machine"))) {
CpuFeatures_StringView_CopyString(value, strings->machine,
sizeof(strings->platform));
} else if (CpuFeatures_StringView_IsEquals(key, str("cpu"))) {
CpuFeatures_StringView_CopyString(value, strings->cpu,
sizeof(strings->platform));
}
}
return !result.eof;
}
static void FillProcCpuInfoData(PPCPlatformStrings* const strings) {
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0) {
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;) {
if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings)) {
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const PPCInfo kEmptyPPCInfo;
PPCInfo GetPPCInfo(void) {
/*
* On Power feature flags aren't currently in cpuinfo so we only look at
* the auxilary vector.
*/
PPCInfo info = kEmptyPPCInfo;
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
for (size_t i = 0; i < PPC_LAST_; ++i) {
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
kSetters[i](&info.features, true);
}
}
return info;
}
static const PPCPlatformStrings kEmptyPPCPlatformStrings;
PPCPlatformStrings GetPPCPlatformStrings(void) {
PPCPlatformStrings strings = kEmptyPPCPlatformStrings;
FillProcCpuInfoData(&strings);
strings.type = CpuFeatures_GetPlatformType();
return strings;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value) {
if (value >= PPC_LAST_) return false;
return kGetters[value](features);
}
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
if (value >= PPC_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

1622
cpu_features/src/cpuinfo_x86.c vendored Normal file

File diff suppressed because it is too large Load Diff

67
cpu_features/src/define_tables.h vendored Normal file
View File

@ -0,0 +1,67 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The following preprocessor constants must be defined before including this
// file:
// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
// This file is to be included once per `cpuinfo_XXX.c` in order to construct
// feature getters and setters functions as well as several enum indexed tables
// from the db file.
// - `kGetters` a table of getters function pointers from feature enum to
// retrieve a feature,
// - `kSetters` a table of setters function pointers from feature enum to set a
// feature,
// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
// flags,
// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
// their feature enum.
#ifndef SRC_DEFINE_TABLES_H_
#define SRC_DEFINE_TABLES_H_
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
#undef FEATURE
#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
[ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
static const HardwareCapabilities kHardwareCapabilities[] = {
DEFINE_TABLE_FEATURES};
#undef FEATURE
#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) { \
features->NAME = value; \
} \
static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) { \
return features->NAME; \
}
DEFINE_TABLE_FEATURES
#undef FEATURE
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
bool) = {DEFINE_TABLE_FEATURES};
#undef FEATURE
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
DEFINE_TABLE_FEATURES};
#undef FEATURE
#endif // SRC_DEFINE_TABLES_H_

62
cpu_features/src/filesystem.c vendored Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/filesystem.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined(CPU_FEATURES_MOCK_FILESYSTEM)
// Implementation will be provided by test/filesystem_for_testing.cc.
#elif defined(_MSC_VER)
#include <io.h>
int CpuFeatures_OpenFile(const char* filename) {
int fd = -1;
_sopen_s(&fd, filename, _O_RDONLY, _SH_DENYWR, _S_IREAD);
return fd;
}
void CpuFeatures_CloseFile(int file_descriptor) { _close(file_descriptor); }
int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
size_t buffer_size) {
return _read(file_descriptor, buffer, (unsigned int)buffer_size);
}
#else
#include <unistd.h>
int CpuFeatures_OpenFile(const char* filename) {
int result;
do {
result = open(filename, O_RDONLY);
} while (result == -1L && errno == EINTR);
return result;
}
void CpuFeatures_CloseFile(int file_descriptor) { close(file_descriptor); }
int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
size_t buffer_size) {
int result;
do {
result = read(file_descriptor, buffer, buffer_size);
} while (result == -1L && errno == EINTR);
return result;
}
#endif

182
cpu_features/src/hwcaps.c vendored Normal file
View File

@ -0,0 +1,182 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/hwcaps.h"
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
#include "internal/string_view.h"
static bool IsSet(const uint32_t mask, const uint32_t value) {
if (mask == 0) return false;
return (value & mask) == mask;
}
bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
const HardwareCapabilities hwcaps) {
return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
}
#ifdef CPU_FEATURES_TEST
// In test mode, hwcaps_for_testing will define the following functions.
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
PlatformType CpuFeatures_GetPlatformType(void);
#else
// Debug facilities
#if defined(NDEBUG)
#define D(...)
#else
#include <stdio.h>
#define D(...) \
do { \
printf(__VA_ARGS__); \
fflush(stdout); \
} while (0)
#endif
////////////////////////////////////////////////////////////////////////////////
// Implementation of GetElfHwcapFromGetauxval
////////////////////////////////////////////////////////////////////////////////
#define AT_HWCAP 16
#define AT_HWCAP2 26
#define AT_PLATFORM 15
#define AT_BASE_PLATFORM 24
#if defined(HAVE_STRONG_GETAUXVAL)
#include <sys/auxv.h>
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
return getauxval(hwcap_type);
}
#elif defined(HAVE_DLFCN_H)
// On Android we probe the system's C library for a 'getauxval' function and
// call it if it exits, or return 0 for failure. This function is available
// since API level 20.
//
// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge
// case where some NDK developers use headers for a platform that is newer than
// the one really targetted by their application. This is typically done to use
// newer native APIs only when running on more recent Android versions, and
// requires careful symbol management.
//
// Note that getauxval() can't really be re-implemented here, because its
// implementation does not parse /proc/self/auxv. Instead it depends on values
// that are passed by the kernel at process-init time to the C runtime
// initialization layer.
#include <dlfcn.h>
typedef unsigned long getauxval_func_t(unsigned long);
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
uint32_t ret = 0;
void *libc_handle = NULL;
getauxval_func_t *func = NULL;
dlerror(); // Cleaning error state before calling dlopen.
libc_handle = dlopen("libc.so", RTLD_NOW);
if (!libc_handle) {
D("Could not dlopen() C library: %s\n", dlerror());
return 0;
}
func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
if (!func) {
D("Could not find getauxval() in C library\n");
} else {
// Note: getauxval() returns 0 on failure. Doesn't touch errno.
ret = (uint32_t)(*func)(hwcap_type);
}
dlclose(libc_handle);
return ret;
}
#else
#error "This platform does not provide hardware capabilities."
#endif
// Implementation of GetHardwareCapabilities for OS that provide
// GetElfHwcapFromGetauxval().
// Fallback when getauxval is not available, retrieves hwcaps from
// "/proc/self/auxv".
static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
struct {
uint32_t tag;
uint32_t value;
} entry;
uint32_t result = 0;
const char filepath[] = "/proc/self/auxv";
const int fd = CpuFeatures_OpenFile(filepath);
if (fd < 0) {
D("Could not open %s\n", filepath);
return 0;
}
for (;;) {
const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
if (ret < 0) {
D("Error while reading %s\n", filepath);
break;
}
// Detect end of list.
if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
break;
}
if (entry.tag == hwcap_type) {
result = entry.value;
break;
}
}
CpuFeatures_CloseFile(fd);
return result;
}
// Retrieves hardware capabilities by first trying to call getauxval, if not
// available falls back to reading "/proc/self/auxv".
static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
if (!hwcaps) {
D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
hwcaps = GetElfHwcapFromProcSelfAuxv(type);
}
return hwcaps;
}
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
HardwareCapabilities capabilities;
capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
return capabilities;
}
PlatformType kEmptyPlatformType;
PlatformType CpuFeatures_GetPlatformType(void) {
PlatformType type = kEmptyPlatformType;
char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
if (platform != NULL)
CpuFeatures_StringView_CopyString(str(platform), type.platform,
sizeof(type.platform));
if (base_platform != NULL)
CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform,
sizeof(type.base_platform));
return type;
}
#endif // CPU_FEATURES_TEST

132
cpu_features/src/stack_line_reader.c vendored Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/stack_line_reader.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include "internal/filesystem.h"
void StackLineReader_Initialize(StackLineReader* reader, int fd) {
reader->view.ptr = reader->buffer;
reader->view.size = 0;
reader->skip_mode = false;
reader->fd = fd;
}
// Replaces the content of buffer with bytes from the file.
static int LoadFullBuffer(StackLineReader* reader) {
const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer,
STACK_LINE_READER_BUFFER_SIZE);
assert(read >= 0);
reader->view.ptr = reader->buffer;
reader->view.size = read;
return read;
}
// Appends with bytes from the file to buffer, filling the remaining space.
static int LoadMore(StackLineReader* reader) {
char* const ptr = reader->buffer + reader->view.size;
const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size;
const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read);
assert(read >= 0);
assert(read <= (int)size_to_read);
reader->view.size += read;
return read;
}
static int IndexOfEol(StackLineReader* reader) {
return CpuFeatures_StringView_IndexOfChar(reader->view, '\n');
}
// Relocate buffer's pending bytes at the beginning of the array and fills the
// remaining space with bytes from the file.
static int BringToFrontAndLoadMore(StackLineReader* reader) {
if (reader->view.size && reader->view.ptr != reader->buffer) {
memmove(reader->buffer, reader->view.ptr, reader->view.size);
}
reader->view.ptr = reader->buffer;
return LoadMore(reader);
}
// Loads chunks of buffer size from disks until it contains a newline character
// or end of file.
static void SkipToNextLine(StackLineReader* reader) {
for (;;) {
const int read = LoadFullBuffer(reader);
if (read == 0) {
break;
} else {
const int eol_index = IndexOfEol(reader);
if (eol_index >= 0) {
reader->view =
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
break;
}
}
}
}
static LineResult CreateLineResult(bool eof, bool full_line, StringView view) {
LineResult result;
result.eof = eof;
result.full_line = full_line;
result.line = view;
return result;
}
// Helper methods to provide clearer semantic in StackLineReader_NextLine.
static LineResult CreateEOFLineResult(StringView view) {
return CreateLineResult(true, true, view);
}
static LineResult CreateTruncatedLineResult(StringView view) {
return CreateLineResult(false, false, view);
}
static LineResult CreateValidLineResult(StringView view) {
return CreateLineResult(false, true, view);
}
LineResult StackLineReader_NextLine(StackLineReader* reader) {
if (reader->skip_mode) {
SkipToNextLine(reader);
reader->skip_mode = false;
}
{
const bool can_load_more =
reader->view.size < STACK_LINE_READER_BUFFER_SIZE;
int eol_index = IndexOfEol(reader);
if (eol_index < 0 && can_load_more) {
const int read = BringToFrontAndLoadMore(reader);
if (read == 0) {
return CreateEOFLineResult(reader->view);
}
eol_index = IndexOfEol(reader);
}
if (eol_index < 0) {
reader->skip_mode = true;
return CreateTruncatedLineResult(reader->view);
}
{
StringView line =
CpuFeatures_StringView_KeepFront(reader->view, eol_index);
reader->view =
CpuFeatures_StringView_PopFront(reader->view, eol_index + 1);
return CreateValidLineResult(line);
}
}
}

182
cpu_features/src/string_view.c vendored Normal file
View File

@ -0,0 +1,182 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/string_view.h"
#include <assert.h>
#include <ctype.h>
#include <string.h>
int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
if (view.ptr && view.size) {
const char* const found = (const char*)memchr(view.ptr, c, view.size);
if (found) {
return (int)(found - view.ptr);
}
}
return -1;
}
int CpuFeatures_StringView_IndexOf(const StringView view,
const StringView sub_view) {
if (sub_view.size) {
StringView remainder = view;
while (remainder.size >= sub_view.size) {
const int found_index =
CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]);
if (found_index < 0) break;
remainder = CpuFeatures_StringView_PopFront(remainder, found_index);
if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) {
return (int)(remainder.ptr - view.ptr);
}
remainder = CpuFeatures_StringView_PopFront(remainder, 1);
}
}
return -1;
}
bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
if (a.size == b.size) {
return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0;
}
return false;
}
bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
return a.ptr && b.ptr && b.size && a.size >= b.size
? memcmp(a.ptr, b.ptr, b.size) == 0
: false;
}
StringView CpuFeatures_StringView_PopFront(const StringView str_view,
size_t count) {
if (count > str_view.size) {
return kEmptyStringView;
}
return view(str_view.ptr + count, str_view.size - count);
}
StringView CpuFeatures_StringView_PopBack(const StringView str_view,
size_t count) {
if (count > str_view.size) {
return kEmptyStringView;
}
return view(str_view.ptr, str_view.size - count);
}
StringView CpuFeatures_StringView_KeepFront(const StringView str_view,
size_t count) {
return count <= str_view.size ? view(str_view.ptr, count) : str_view;
}
char CpuFeatures_StringView_Front(const StringView view) {
assert(view.size);
assert(view.ptr);
return view.ptr[0];
}
char CpuFeatures_StringView_Back(const StringView view) {
assert(view.size);
return view.ptr[view.size - 1];
}
StringView CpuFeatures_StringView_TrimWhitespace(StringView view) {
while (view.size && isspace(CpuFeatures_StringView_Front(view)))
view = CpuFeatures_StringView_PopFront(view, 1);
while (view.size && isspace(CpuFeatures_StringView_Back(view)))
view = CpuFeatures_StringView_PopBack(view, 1);
return view;
}
static int HexValue(const char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
// Returns -1 if view contains non digits.
static int ParsePositiveNumberWithBase(const StringView view, int base) {
int result = 0;
StringView remainder = view;
for (; remainder.size;
remainder = CpuFeatures_StringView_PopFront(remainder, 1)) {
const int value = HexValue(CpuFeatures_StringView_Front(remainder));
if (value < 0 || value >= base) return -1;
result = (result * base) + value;
}
return result;
}
int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) {
if (view.size) {
const StringView hex_prefix = str("0x");
if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) {
const StringView span_no_prefix =
CpuFeatures_StringView_PopFront(view, hex_prefix.size);
return ParsePositiveNumberWithBase(span_no_prefix, 16);
}
return ParsePositiveNumberWithBase(view, 10);
}
return -1;
}
void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
size_t dst_size) {
if (dst_size > 0) {
const size_t max_copy_size = dst_size - 1;
const size_t copy_size =
src.size > max_copy_size ? max_copy_size : src.size;
memcpy(dst, src.ptr, copy_size);
dst[copy_size] = '\0';
}
}
bool CpuFeatures_StringView_HasWord(const StringView line,
const char* const word_str) {
const StringView word = str(word_str);
StringView remainder = line;
for (;;) {
const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word);
if (index_of_word < 0) {
return false;
} else {
const StringView before =
CpuFeatures_StringView_KeepFront(line, index_of_word);
const StringView after =
CpuFeatures_StringView_PopFront(line, index_of_word + word.size);
const bool valid_before =
before.size == 0 || CpuFeatures_StringView_Back(before) == ' ';
const bool valid_after =
after.size == 0 || CpuFeatures_StringView_Front(after) == ' ';
if (valid_before && valid_after) return true;
remainder =
CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size);
}
}
return false;
}
bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line,
StringView* key,
StringView* value) {
const StringView sep = str(": ");
const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep);
if (index_of_separator < 0) return false;
*value = CpuFeatures_StringView_TrimWhitespace(
CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size));
*key = CpuFeatures_StringView_TrimWhitespace(
CpuFeatures_StringView_KeepFront(line, index_of_separator));
return true;
}

View File

@ -0,0 +1,438 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This program dumps current host data to the standard output.
// Output can be text or json if the `--json` flag is passed.
#include <assert.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#if defined(CPU_FEATURES_ARCH_X86)
#include "cpuinfo_x86.h"
#elif defined(CPU_FEATURES_ARCH_ARM)
#include "cpuinfo_arm.h"
#elif defined(CPU_FEATURES_ARCH_AARCH64)
#include "cpuinfo_aarch64.h"
#elif defined(CPU_FEATURES_ARCH_MIPS)
#include "cpuinfo_mips.h"
#elif defined(CPU_FEATURES_ARCH_PPC)
#include "cpuinfo_ppc.h"
#endif
// Design principles
// -----------------
// We build a tree structure containing all the data to be displayed.
// Then depending on the output type (text or json) we walk the tree and display
// the data accordingly.
// We use a bump allocator to allocate strings and nodes of the tree,
// Memory is not intended to be reclaimed.
typedef struct {
char* ptr;
size_t size;
} BumpAllocator;
char gGlobalBuffer[64 * 1024];
BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
.size = sizeof(gGlobalBuffer)};
static void internal_error() {
fputs("internal error\n", stderr);
exit(EXIT_FAILURE);
}
#define ALIGN 8
static void assertAligned() {
if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
}
static void BA_Align() {
while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
--gBumpAllocator.size;
++gBumpAllocator.ptr;
}
assertAligned();
}
// Update the available memory left in the BumpAllocator.
static void* BA_Bump(size_t size) {
assertAligned();
// Align size to next 8B boundary.
size = (size + ALIGN - 1) / ALIGN * ALIGN;
if (gBumpAllocator.size < size) internal_error();
void* ptr = gBumpAllocator.ptr;
gBumpAllocator.size -= size;
gBumpAllocator.ptr += size;
return ptr;
}
// The type of the nodes in the tree.
typedef enum {
NT_INVALID,
NT_INT,
NT_MAP,
NT_MAP_ENTRY,
NT_ARRAY,
NT_ARRAY_ELEMENT,
NT_STRING,
} NodeType;
// The node in the tree.
typedef struct Node {
NodeType type;
unsigned integer;
const char* string;
struct Node* value;
struct Node* next;
} Node;
// Creates an initialized Node.
static Node* BA_CreateNode(NodeType type) {
Node* tv = (Node*)BA_Bump(sizeof(Node));
assert(tv);
*tv = (Node){.type = type};
return tv;
}
// Adds an integer node.
static Node* CreateInt(int value) {
Node* tv = BA_CreateNode(NT_INT);
tv->integer = value;
return tv;
}
// Adds a string node.
// `value` must outlive the tree.
static Node* CreateConstantString(const char* value) {
Node* tv = BA_CreateNode(NT_STRING);
tv->string = value;
return tv;
}
// Adds a map node.
static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
// Adds an array node.
static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
// Adds a formatted string node.
static Node* CreatePrintfString(const char* format, ...) {
va_list arglist;
va_start(arglist, format);
char* const ptr = gBumpAllocator.ptr;
const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist);
va_end(arglist);
if (written < 0 || written >= (int)gBumpAllocator.size) internal_error();
return CreateConstantString((char*)BA_Bump(written));
}
// Adds a string node.
static Node* CreateString(const char* value) {
return CreatePrintfString("%s", value);
}
// Adds a map entry node.
static void AddMapEntry(Node* map, const char* key, Node* value) {
assert(map && map->type == NT_MAP);
Node* current = map;
while (current->next) current = current->next;
current->next = (Node*)BA_Bump(sizeof(Node));
*current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value};
}
// Adds an array element node.
static void AddArrayElement(Node* array, Node* value) {
assert(array && array->type == NT_ARRAY);
Node* current = array;
while (current->next) current = current->next;
current->next = (Node*)BA_Bump(sizeof(Node));
*current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value};
}
static int cmp(const void* p1, const void* p2) {
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
}
#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
static void AddFlags(Node* map, const FeatureType* features) { \
size_t i; \
const char* ptrs[LastEnum] = {0}; \
size_t count = 0; \
for (i = 0; i < LastEnum; ++i) { \
if (HasFeature(features, i)) { \
ptrs[count] = FeatureName(i); \
++count; \
} \
} \
qsort((void*)ptrs, count, sizeof(char*), cmp); \
Node* const array = CreateArray(); \
for (i = 0; i < count; ++i) \
AddArrayElement(array, CreateConstantString(ptrs[i])); \
AddMapEntry(map, "flags", array); \
}
#if defined(CPU_FEATURES_ARCH_X86)
DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
X86_LAST_)
#elif defined(CPU_FEATURES_ARCH_ARM)
DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
ARM_LAST_)
#elif defined(CPU_FEATURES_ARCH_AARCH64)
DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
Aarch64Features, AARCH64_LAST_)
#elif defined(CPU_FEATURES_ARCH_MIPS)
DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
MipsFeatures, MIPS_LAST_)
#elif defined(CPU_FEATURES_ARCH_PPC)
DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
PPC_LAST_)
#endif
// Prints a json string with characters escaping.
static void printJsonString(const char* str) {
putchar('"');
for (; str && *str; ++str) {
switch (*str) {
case '\"':
case '\\':
case '/':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
putchar('\\');
}
putchar(*str);
}
putchar('"');
}
// Walks a Node and print it as json.
static void printJson(const Node* current) {
assert(current);
switch (current->type) {
case NT_INVALID:
break;
case NT_INT:
printf("%d", current->integer);
break;
case NT_STRING:
printJsonString(current->string);
break;
case NT_ARRAY:
putchar('[');
if (current->next) printJson(current->next);
putchar(']');
break;
case NT_MAP:
putchar('{');
if (current->next) printJson(current->next);
putchar('}');
break;
case NT_MAP_ENTRY:
printf("\"%s\":", current->string);
printJson(current->value);
if (current->next) {
putchar(',');
printJson(current->next);
}
break;
case NT_ARRAY_ELEMENT:
printJson(current->value);
if (current->next) {
putchar(',');
printJson(current->next);
}
break;
}
}
// Walks a Node and print it as text.
static void printTextField(const Node* current) {
switch (current->type) {
case NT_INVALID:
break;
case NT_INT:
printf("%3d (0x%02X)", current->integer, current->integer);
break;
case NT_STRING:
fputs(current->string, stdout);
break;
case NT_ARRAY:
if (current->next) printTextField(current->next);
break;
case NT_MAP:
if (current->next) {
printf("{");
printJson(current->next);
printf("}");
}
break;
case NT_MAP_ENTRY:
printf("%-15s : ", current->string);
printTextField(current->value);
if (current->next) {
putchar('\n');
printTextField(current->next);
}
break;
case NT_ARRAY_ELEMENT:
printTextField(current->value);
if (current->next) {
putchar(',');
printTextField(current->next);
}
break;
}
}
static void printTextRoot(const Node* current) {
if (current->type == NT_MAP && current->next) printTextField(current->next);
}
static void showUsage(const char* name) {
printf(
"\n"
"Usage: %s [options]\n"
" Options:\n"
" -h | --help Show help message.\n"
" -j | --json Format output as json instead of plain text.\n"
"\n",
name);
}
static Node* GetCacheTypeString(CacheType cache_type) {
switch (cache_type) {
case CPU_FEATURE_CACHE_NULL:
return CreateConstantString("null");
case CPU_FEATURE_CACHE_DATA:
return CreateConstantString("data");
case CPU_FEATURE_CACHE_INSTRUCTION:
return CreateConstantString("instruction");
case CPU_FEATURE_CACHE_UNIFIED:
return CreateConstantString("unified");
case CPU_FEATURE_CACHE_TLB:
return CreateConstantString("tlb");
case CPU_FEATURE_CACHE_DTLB:
return CreateConstantString("dtlb");
case CPU_FEATURE_CACHE_STLB:
return CreateConstantString("stlb");
case CPU_FEATURE_CACHE_PREFETCH:
return CreateConstantString("prefetch");
}
}
static void AddCacheInfo(Node* root, const CacheInfo* cache_info) {
Node* array = CreateArray();
for (int i = 0; i < cache_info->size; ++i) {
CacheLevelInfo info = cache_info->levels[i];
Node* map = CreateMap();
AddMapEntry(map, "level", CreateInt(info.level));
AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type));
AddMapEntry(map, "cache_size", CreateInt(info.cache_size));
AddMapEntry(map, "ways", CreateInt(info.ways));
AddMapEntry(map, "line_size", CreateInt(info.line_size));
AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries));
AddMapEntry(map, "partitioning", CreateInt(info.partitioning));
AddArrayElement(array, map);
}
AddMapEntry(root, "cache_info", array);
}
static Node* CreateTree() {
Node* root = CreateMap();
#if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49];
const X86Info info = GetX86Info();
const CacheInfo cache_info = GetX86CacheInfo();
FillX86BrandString(brand_string);
AddMapEntry(root, "arch", CreateString("x86"));
AddMapEntry(root, "brand", CreateString(brand_string));
AddMapEntry(root, "family", CreateInt(info.family));
AddMapEntry(root, "model", CreateInt(info.model));
AddMapEntry(root, "stepping", CreateInt(info.stepping));
AddMapEntry(root, "uarch",
CreateString(
GetX86MicroarchitectureName(GetX86Microarchitecture(&info))));
AddFlags(root, &info.features);
AddCacheInfo(root, &cache_info);
#elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo();
AddMapEntry(root, "arch", CreateString("ARM"));
AddMapEntry(root, "implementer", CreateInt(info.implementer));
AddMapEntry(root, "architecture", CreateInt(info.architecture));
AddMapEntry(root, "variant", CreateInt(info.variant));
AddMapEntry(root, "part", CreateInt(info.part));
AddMapEntry(root, "revision", CreateInt(info.revision));
AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info();
AddMapEntry(root, "arch", CreateString("aarch64"));
AddMapEntry(root, "implementer", CreateInt(info.implementer));
AddMapEntry(root, "variant", CreateInt(info.variant));
AddMapEntry(root, "part", CreateInt(info.part));
AddMapEntry(root, "revision", CreateInt(info.revision));
AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS)
const MipsInfo info = GetMipsInfo();
AddMapEntry(root, "arch", CreateString("mips"));
AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_PPC)
const PPCInfo info = GetPPCInfo();
const PPCPlatformStrings strings = GetPPCPlatformStrings();
AddMapEntry(root, "arch", CreateString("ppc"));
AddMapEntry(root, "platform", CreateString(strings.platform));
AddMapEntry(root, "model", CreateString(strings.model));
AddMapEntry(root, "machine", CreateString(strings.machine));
AddMapEntry(root, "cpu", CreateString(strings.cpu));
AddMapEntry(root, "instruction", CreateString(strings.type.platform));
AddMapEntry(root, "microarchitecture",
CreateString(strings.type.base_platform));
AddFlags(root, &info.features);
#endif
return root;
}
int main(int argc, char** argv) {
BA_Align();
const Node* const root = CreateTree();
bool outputJson = false;
int i = 1;
for (; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
outputJson = true;
} else {
showUsage(argv[0]);
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
}
if (outputJson)
printJson(root);
else
printTextRoot(root);
putchar('\n');
return EXIT_SUCCESS;
}

85
cpu_features/test/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,85 @@
#
# libraries for tests
#
include_directories(../include)
add_definitions(-DCPU_FEATURES_TEST)
##------------------------------------------------------------------------------
add_library(string_view ../src/string_view.c)
##------------------------------------------------------------------------------
add_library(filesystem_for_testing filesystem_for_testing.cc)
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
##------------------------------------------------------------------------------
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(stack_line_reader ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024)
target_link_libraries(stack_line_reader string_view)
##------------------------------------------------------------------------------
add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
#
# tests
#
link_libraries(gtest gmock_main)
## bit_utils_test
add_executable(bit_utils_test bit_utils_test.cc)
target_link_libraries(bit_utils_test)
add_test(NAME bit_utils_test COMMAND bit_utils_test)
##------------------------------------------------------------------------------
## string_view_test
add_executable(string_view_test string_view_test.cc ../src/string_view.c)
target_link_libraries(string_view_test string_view)
add_test(NAME string_view_test COMMAND string_view_test)
##------------------------------------------------------------------------------
## stack_line_reader_test
add_executable(stack_line_reader_test stack_line_reader_test.cc)
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
##------------------------------------------------------------------------------
## cpuinfo_x86_test
if(PROCESSOR_IS_X86)
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
if(APPLE)
target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
endif()
target_link_libraries(cpuinfo_x86_test all_libraries)
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_arm_test
if(PROCESSOR_IS_ARM)
add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c)
target_link_libraries(cpuinfo_arm_test all_libraries)
add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_aarch64_test
if(PROCESSOR_IS_AARCH64)
add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c)
target_link_libraries(cpuinfo_aarch64_test all_libraries)
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_mips_test
if(PROCESSOR_IS_MIPS)
add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c)
target_link_libraries(cpuinfo_mips_test all_libraries)
add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_ppc_test
if(PROCESSOR_IS_POWER)
add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/cpuinfo_ppc.c)
target_link_libraries(cpuinfo_ppc_test all_libraries)
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
endif()

53
cpu_features/test/bit_utils_test.cc vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/bit_utils.h"
#include "gtest/gtest.h"
namespace cpu_features {
namespace {
TEST(UtilsTest, IsBitSet) {
for (size_t bit_set = 0; bit_set < 32; ++bit_set) {
const uint32_t value = 1UL << bit_set;
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_EQ(IsBitSet(value, i), i == bit_set);
}
}
// testing 0, all bits should be 0.
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_FALSE(IsBitSet(0, i));
}
// testing ~0, all bits should be 1.
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_TRUE(IsBitSet(-1, i));
}
}
TEST(UtilsTest, ExtractBitRange) {
// Extracting all bits gives the same number.
EXPECT_EQ(ExtractBitRange(123, 31, 0), 123);
// Extracting 1 bit gives parity.
EXPECT_EQ(ExtractBitRange(123, 0, 0), 1);
EXPECT_EQ(ExtractBitRange(122, 0, 0), 0);
EXPECT_EQ(ExtractBitRange(0xF0, 7, 4), 0xF);
EXPECT_EQ(ExtractBitRange(0x42 << 2, 10, 2), 0x42);
}
} // namespace
} // namespace cpu_features

View File

@ -0,0 +1,171 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_aarch64.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
TEST(CpuinfoAarch64Test, FromHardwareCap) {
SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_FALSE(info.features.asimd);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
EXPECT_FALSE(info.features.atomics);
EXPECT_FALSE(info.features.fphp);
EXPECT_FALSE(info.features.asimdhp);
EXPECT_FALSE(info.features.cpuid);
EXPECT_FALSE(info.features.asimdrdm);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.fcma);
EXPECT_FALSE(info.features.lrcpc);
EXPECT_FALSE(info.features.dcpop);
EXPECT_FALSE(info.features.sha3);
EXPECT_FALSE(info.features.sm3);
EXPECT_FALSE(info.features.sm4);
EXPECT_FALSE(info.features.asimddp);
EXPECT_FALSE(info.features.sha512);
EXPECT_FALSE(info.features.sve);
EXPECT_FALSE(info.features.asimdfhm);
EXPECT_FALSE(info.features.dit);
EXPECT_FALSE(info.features.uscat);
EXPECT_FALSE(info.features.ilrcpc);
EXPECT_FALSE(info.features.flagm);
EXPECT_FALSE(info.features.ssbs);
EXPECT_FALSE(info.features.sb);
EXPECT_FALSE(info.features.paca);
EXPECT_FALSE(info.features.pacg);
}
TEST(CpuinfoAarch64Test, FromHardwareCap2) {
SetHardwareCapabilities(AARCH64_HWCAP_FP,
AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.sve2);
EXPECT_TRUE(info.features.bti);
EXPECT_FALSE(info.features.dcpodp);
EXPECT_FALSE(info.features.sveaes);
EXPECT_FALSE(info.features.svepmull);
EXPECT_FALSE(info.features.svebitperm);
EXPECT_FALSE(info.features.svesha3);
EXPECT_FALSE(info.features.svesm4);
EXPECT_FALSE(info.features.flagm2);
EXPECT_FALSE(info.features.frint);
EXPECT_FALSE(info.features.svei8mm);
EXPECT_FALSE(info.features.svef32mm);
EXPECT_FALSE(info.features.svef64mm);
EXPECT_FALSE(info.features.svebf16);
EXPECT_FALSE(info.features.i8mm);
EXPECT_FALSE(info.features.bf16);
EXPECT_FALSE(info.features.dgh);
EXPECT_FALSE(info.features.rng);
}
TEST(CpuinfoAarch64Test, ARMCortexA53) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : AArch64 Processor rev 3 (aarch64)
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: AArch64
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 3)");
const auto info = GetAarch64Info();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x0);
EXPECT_EQ(info.part, 0xd03);
EXPECT_EQ(info.revision, 3);
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.asimd);
EXPECT_TRUE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.pmull);
EXPECT_TRUE(info.features.sha1);
EXPECT_TRUE(info.features.sha2);
EXPECT_TRUE(info.features.crc32);
EXPECT_FALSE(info.features.atomics);
EXPECT_FALSE(info.features.fphp);
EXPECT_FALSE(info.features.asimdhp);
EXPECT_FALSE(info.features.cpuid);
EXPECT_FALSE(info.features.asimdrdm);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.fcma);
EXPECT_FALSE(info.features.lrcpc);
EXPECT_FALSE(info.features.dcpop);
EXPECT_FALSE(info.features.sha3);
EXPECT_FALSE(info.features.sm3);
EXPECT_FALSE(info.features.sm4);
EXPECT_FALSE(info.features.asimddp);
EXPECT_FALSE(info.features.sha512);
EXPECT_FALSE(info.features.sve);
EXPECT_FALSE(info.features.asimdfhm);
EXPECT_FALSE(info.features.dit);
EXPECT_FALSE(info.features.uscat);
EXPECT_FALSE(info.features.ilrcpc);
EXPECT_FALSE(info.features.flagm);
EXPECT_FALSE(info.features.ssbs);
EXPECT_FALSE(info.features.sb);
EXPECT_FALSE(info.features.paca);
EXPECT_FALSE(info.features.pacg);
EXPECT_FALSE(info.features.dcpodp);
EXPECT_FALSE(info.features.sve2);
EXPECT_FALSE(info.features.sveaes);
EXPECT_FALSE(info.features.svepmull);
EXPECT_FALSE(info.features.svebitperm);
EXPECT_FALSE(info.features.svesha3);
EXPECT_FALSE(info.features.svesm4);
EXPECT_FALSE(info.features.flagm2);
EXPECT_FALSE(info.features.frint);
EXPECT_FALSE(info.features.svei8mm);
EXPECT_FALSE(info.features.svef32mm);
EXPECT_FALSE(info.features.svef64mm);
EXPECT_FALSE(info.features.svebf16);
EXPECT_FALSE(info.features.i8mm);
EXPECT_FALSE(info.features.bf16);
EXPECT_FALSE(info.features.dgh);
EXPECT_FALSE(info.features.rng);
EXPECT_FALSE(info.features.bti);
}
} // namespace
} // namespace cpu_features

354
cpu_features/test/cpuinfo_arm_test.cc vendored Normal file
View File

@ -0,0 +1,354 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_arm.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
TEST(CpuinfoArmTest, FromHardwareCap) {
SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.vfp); // triggered by vfpv3
EXPECT_TRUE(info.features.vfpv3); // triggered by neon
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.crc32);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
// check some random features with EnumValue():
EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
// out of bound EnumValue() check
EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
}
TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv7 Processor rev 3 (v71)
BogoMIPS : 120.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc0f
CPU revision : 3)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x2);
EXPECT_EQ(info.part, 0xc0f);
EXPECT_EQ(info.revision, 3);
EXPECT_EQ(info.architecture, 7);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_FALSE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_TRUE(info.features.vfpv4);
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_TRUE(info.features.vfpd32);
EXPECT_TRUE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Linux test-case
TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS : 697.95
Features : half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 7
Hardware : BCM2835
Revision : 9000c1
Serial : 000000006cd946f3)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x0);
EXPECT_EQ(info.part, 0xb76);
EXPECT_EQ(info.revision, 7);
EXPECT_EQ(info.architecture, 6);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_TRUE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.neon);
EXPECT_FALSE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 50.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x4
CPU part : 0xc09
CPU revision : 1
processor : 1
model name : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 50.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x4
CPU part : 0xc09
CPU revision : 1
Hardware : Marvell Armada 380/385 (Device Tree)
Revision : 0000
Serial : 0000000000000000)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x4);
EXPECT_EQ(info.part, 0xc09);
EXPECT_EQ(info.revision, 1);
EXPECT_EQ(info.architecture, 7);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_FALSE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_TRUE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Android test-case
// http://code.google.com/p/android/issues/detail?id=10812
TEST(CpuinfoArmTest, InvalidArmv7) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : ARMv6-compatible processor rev 6 (v6l)
BogoMIPS : 199.47
Features : swp half thumb fastmult vfp edsp java
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 6
Hardware : SPICA
Revision : 0020
Serial : 33323613546d00ec )");
const auto info = GetArmInfo();
EXPECT_EQ(info.architecture, 6);
EXPECT_TRUE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_TRUE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.neon);
EXPECT_FALSE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_FALSE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Android test-case
// https://crbug.com/341598.
TEST(CpuinfoArmTest, InvalidNeon) {
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor: ARMv7 Processory rev 0 (v71)
processor: 0
BogoMIPS: 13.50
Processor: 1
BogoMIPS: 13.50
Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
CPU implementer : 0x51
CPU architecture: 7
CPU variant: 0x1
CPU part: 0x04d
CPU revision: 0
Hardware: SAMSUNG M2
Revision: 0010
Serial: 00001e030000354e)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.swp);
EXPECT_FALSE(info.features.neon);
}
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
// support.
TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x0
CPU part : 0x6f
CPU revision : 2)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_EQ(GetArmCpuId(&info), 0x510006f2);
}
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
// support.
TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x0
CPU part : 0x6f
CPU revision : 3)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_EQ(GetArmCpuId(&info), 0x510006f3);
}
// The emulator-specific Android 4.2 kernel fails to report support for the
// 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual
// CPU implemented by the emulator.
TEST(CpuinfoArmTest, EmulatorSpecificIdiv) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 629.14
Features : swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc08
CPU revision : 0
Hardware : Goldfish
Revision : 0000
Serial : 0000000000000000)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
}
} // namespace
} // namespace cpu_features

126
cpu_features/test/cpuinfo_mips_test.cc vendored Normal file
View File

@ -0,0 +1,126 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_mips.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
namespace cpu_features {
namespace {
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
TEST(CpuinfoMipsTest, FromHardwareCapBoth) {
SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetMipsInfo();
EXPECT_TRUE(info.features.msa);
EXPECT_FALSE(info.features.eva);
EXPECT_TRUE(info.features.r6);
}
TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) {
SetHardwareCapabilities(MIPS_HWCAP_MSA, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetMipsInfo();
EXPECT_TRUE(info.features.msa);
EXPECT_FALSE(info.features.eva);
}
TEST(CpuinfoMipsTest, Ci40) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0)
machine : IMG Marduk Ci40 with cc2520
processor : 0
cpu model : MIPS interAptiv (multi) V2.0 FPU V0.0
BogoMIPS : 363.72
wait instruction : yes
microsecond timers : yes
tlb_entries : 64
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16 dsp mt eva
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
VPE : 0
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_TRUE(info.features.eva);
}
TEST(CpuinfoMipsTest, AR7161) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(system type : Atheros AR7161 rev 2
machine : NETGEAR WNDR3700/WNDR3800/WNDRMAC
processor : 0
cpu model : MIPS 24Kc V7.4
BogoMIPS : 452.19
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0000, 0x0f98, 0x0f78, 0x0df8]
ASEs implemented : mips16
shadow register sets : 1
kscratch registers : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
}
TEST(CpuinfoMipsTest, Goldfish) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(system type : MIPS-Goldfish
Hardware : goldfish
Revison : 1
processor : 0
cpu model : MIPS 24Kc V0.0 FPU V0.0
BogoMIPS : 1042.02
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
ASEs implemented :
shadow register sets : 1
core : 0
VCED exceptions : not available
VCEI exceptions : not available
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
}
} // namespace
} // namespace cpu_features

119
cpu_features/test/cpuinfo_ppc_test.cc vendored Normal file
View File

@ -0,0 +1,119 @@
// Copyright 2018 IBM.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_ppc.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
namespace cpu_features {
namespace {
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
TEST(CpustringsPPCTest, FromHardwareCap) {
SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX,
PPC_FEATURE2_ARCH_3_00);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetPPCInfo();
EXPECT_TRUE(info.features.fpu);
EXPECT_FALSE(info.features.mmu);
EXPECT_TRUE(info.features.vsx);
EXPECT_TRUE(info.features.arch300);
EXPECT_FALSE(info.features.power4);
EXPECT_FALSE(info.features.altivec);
EXPECT_FALSE(info.features.vcrypto);
EXPECT_FALSE(info.features.htm);
}
TEST(CpustringsPPCTest, Blade) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 14
cpu : POWER7 (architected), altivec supported
clock : 3000.000000MHz
revision : 2.1 (pvr 003f 0201)
processor : 15
cpu : POWER7 (architected), altivec supported
clock : 3000.000000MHz
revision : 2.1 (pvr 003f 0201)
timebase : 512000000
platform : pSeries
model : IBM,8406-70Y
machine : CHRP IBM,8406-70Y)");
SetPlatformTypes("power7", "power8");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "pSeries");
ASSERT_STREQ(strings.model, "IBM,8406-70Y");
ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y");
ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported");
ASSERT_STREQ(strings.type.platform, "power7");
ASSERT_STREQ(strings.type.base_platform, "power8");
}
TEST(CpustringsPPCTest, Firestone) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 126
cpu : POWER8 (raw), altivec supported
clock : 2061.000000MHz
revision : 2.0 (pvr 004d 0200)
processor : 127
cpu : POWER8 (raw), altivec supported
clock : 2061.000000MHz
revision : 2.0 (pvr 004d 0200)
timebase : 512000000
platform : PowerNV
model : 8335-GTA
machine : PowerNV 8335-GTA
firmware : OPAL v3)");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "PowerNV");
ASSERT_STREQ(strings.model, "8335-GTA");
ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA");
ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported");
}
TEST(CpustringsPPCTest, w8) {
DisableHardwareCapabilities();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 143
cpu : POWER9, altivec supported
clock : 2300.000000MHz
revision : 2.2 (pvr 004e 1202)
timebase : 512000000
platform : PowerNV
model : 0000000000000000
machine : PowerNV 0000000000000000
firmware : OPAL
MMU : Radix)");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "PowerNV");
ASSERT_STREQ(strings.model, "0000000000000000");
ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000");
ASSERT_STREQ(strings.cpu, "POWER9, altivec supported");
}
} // namespace
} // namespace cpu_features

533
cpu_features/test/cpuinfo_x86_test.cc vendored Normal file
View File

@ -0,0 +1,533 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_x86.h"
#include <cassert>
#include <cstdio>
#include <map>
#include <set>
#if defined(CPU_FEATURES_OS_WINDOWS)
#include <windows.h> // IsProcessorFeaturePresent
#endif // CPU_FEATURES_OS_WINDOWS
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "internal/cpuid_x86.h"
namespace cpu_features {
class FakeCpu {
public:
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const {
const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
if (itr != cpuid_leaves_.end()) {
return itr->second;
}
return {0, 0, 0, 0};
}
uint32_t GetXCR0Eax() const { return xcr0_eax_; }
void SetLeaves(std::map<std::pair<uint32_t, int>, Leaf> configuration) {
cpuid_leaves_ = std::move(configuration);
}
void SetOsBackupsExtendedRegisters(bool os_backups_extended_registers) {
xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
}
#if defined(CPU_FEATURES_OS_DARWIN)
bool GetDarwinSysCtlByName(std::string name) const {
return darwin_sysctlbyname_.count(name);
}
void SetDarwinSysCtlByName(std::string name) {
darwin_sysctlbyname_.insert(name);
}
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_WINDOWS)
bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
return windows_isprocessorfeaturepresent_.count(ProcessorFeature);
}
void SetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
windows_isprocessorfeaturepresent_.insert(ProcessorFeature);
}
#endif // CPU_FEATURES_OS_WINDOWS
private:
std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
#if defined(CPU_FEATURES_OS_DARWIN)
std::set<std::string> darwin_sysctlbyname_;
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_WINDOWS)
std::set<DWORD> windows_isprocessorfeaturepresent_;
#endif // CPU_FEATURES_OS_WINDOWS
uint32_t xcr0_eax_;
};
FakeCpu* g_fake_cpu = nullptr;
extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
}
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
#if defined(CPU_FEATURES_OS_DARWIN)
extern "C" bool GetDarwinSysCtlByName(const char* name) {
return g_fake_cpu->GetDarwinSysCtlByName(name);
}
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_WINDOWS)
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature);
}
#endif // CPU_FEATURES_OS_WINDOWS
namespace {
class CpuidX86Test : public ::testing::Test {
protected:
void SetUp() override { g_fake_cpu = new FakeCpu(); }
void TearDown() override { delete g_fake_cpu; }
};
TEST_F(CpuidX86Test, SandyBridge) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x02A);
EXPECT_EQ(info.stepping, 0x06);
// Leaf 7 is zeroed out so none of the Leaf 7 flags are set.
const auto features = info.features;
EXPECT_FALSE(features.erms);
EXPECT_FALSE(features.avx2);
EXPECT_FALSE(features.avx512f);
EXPECT_FALSE(features.avx512cd);
EXPECT_FALSE(features.avx512er);
EXPECT_FALSE(features.avx512pf);
EXPECT_FALSE(features.avx512bw);
EXPECT_FALSE(features.avx512dq);
EXPECT_FALSE(features.avx512vl);
EXPECT_FALSE(features.avx512ifma);
EXPECT_FALSE(features.avx512vbmi);
EXPECT_FALSE(features.avx512vbmi2);
EXPECT_FALSE(features.avx512vnni);
EXPECT_FALSE(features.avx512bitalg);
EXPECT_FALSE(features.avx512vpopcntdq);
EXPECT_FALSE(features.avx512_4vnniw);
EXPECT_FALSE(features.avx512_4fmaps);
// All old cpu features should be set.
EXPECT_TRUE(features.aes);
EXPECT_TRUE(features.ssse3);
EXPECT_TRUE(features.sse4_1);
EXPECT_TRUE(features.sse4_2);
EXPECT_TRUE(features.avx);
EXPECT_FALSE(features.sha);
EXPECT_TRUE(features.popcnt);
EXPECT_FALSE(features.movbe);
EXPECT_FALSE(features.rdrnd);
}
const int KiB = 1024;
const int MiB = 1024 * KiB;
TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
});
// avx is disabled if os does not support backing up ymm registers.
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
EXPECT_FALSE(GetX86Info().features.avx);
// avx is disabled if os does not support backing up ymm registers.
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
EXPECT_TRUE(GetX86Info().features.avx);
}
TEST_F(CpuidX86Test, SkyLake) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x04E);
EXPECT_EQ(info.stepping, 0x03);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
}
TEST_F(CpuidX86Test, Branding) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
{{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
{{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
{{0x80000004, 0}, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}},
});
char brand_string[49];
FillX86BrandString(brand_string);
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
}
TEST_F(CpuidX86Test, KabyLakeCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
{{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}},
{{0x00000004, 2}, Leaf{0x1C004143, 0x00C0003F, 0x000003FF, 0x00000000}},
{{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000002}},
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
{{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
{{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
});
const auto info = GetX86CacheInfo();
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
EXPECT_EQ(info.levels[0].cache_type, 1);
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[0].ways, 8);
EXPECT_EQ(info.levels[0].line_size, 64);
EXPECT_EQ(info.levels[0].tlb_entries, 64);
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
EXPECT_EQ(info.levels[1].cache_type, 2);
EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[1].ways, 8);
EXPECT_EQ(info.levels[1].line_size, 64);
EXPECT_EQ(info.levels[1].tlb_entries, 64);
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
EXPECT_EQ(info.levels[2].cache_type, 3);
EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
EXPECT_EQ(info.levels[2].ways, 4);
EXPECT_EQ(info.levels[2].line_size, 64);
EXPECT_EQ(info.levels[2].tlb_entries, 1024);
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
EXPECT_EQ(info.levels[3].cache_type, 3);
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
EXPECT_EQ(info.levels[3].ways, 12);
EXPECT_EQ(info.levels[3].line_size, 64);
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
EXPECT_EQ(info.levels[3].partitioning, 1);
}
TEST_F(CpuidX86Test, HSWCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
{{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}},
{{0x00000004, 2}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
{{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000006}},
{{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
{{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
{{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
});
const auto info = GetX86CacheInfo();
EXPECT_EQ(info.size, 4);
EXPECT_EQ(info.levels[0].level, 1);
EXPECT_EQ(info.levels[0].cache_type, 1);
EXPECT_EQ(info.levels[0].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[0].ways, 8);
EXPECT_EQ(info.levels[0].line_size, 64);
EXPECT_EQ(info.levels[0].tlb_entries, 64);
EXPECT_EQ(info.levels[0].partitioning, 1);
EXPECT_EQ(info.levels[1].level, 1);
EXPECT_EQ(info.levels[1].cache_type, 2);
EXPECT_EQ(info.levels[1].cache_size, 32 * KiB);
EXPECT_EQ(info.levels[1].ways, 8);
EXPECT_EQ(info.levels[1].line_size, 64);
EXPECT_EQ(info.levels[1].tlb_entries, 64);
EXPECT_EQ(info.levels[1].partitioning, 1);
EXPECT_EQ(info.levels[2].level, 2);
EXPECT_EQ(info.levels[2].cache_type, 3);
EXPECT_EQ(info.levels[2].cache_size, 256 * KiB);
EXPECT_EQ(info.levels[2].ways, 8);
EXPECT_EQ(info.levels[2].line_size, 64);
EXPECT_EQ(info.levels[2].tlb_entries, 512);
EXPECT_EQ(info.levels[2].partitioning, 1);
EXPECT_EQ(info.levels[3].level, 3);
EXPECT_EQ(info.levels[3].cache_type, 3);
EXPECT_EQ(info.levels[3].cache_size, 6 * MiB);
EXPECT_EQ(info.levels[3].ways, 12);
EXPECT_EQ(info.levels[3].line_size, 64);
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
EXPECT_EQ(info.levels[3].partitioning, 1);
}
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
TEST_F(CpuidX86Test, AMD_K15) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
{{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
{{0x80000001, 0}, Leaf{0x00630F81, 0x10000000, 0x0FEBBFFF, 0x2FD3FBFF}},
{{0x80000002, 0}, Leaf{0x20444D41, 0x372D3841, 0x4B303736, 0x64615220}},
{{0x80000003, 0}, Leaf{0x206E6F65, 0x202C3752, 0x43203031, 0x75706D6F}},
{{0x80000004, 0}, Leaf{0x43206574, 0x7365726F, 0x2B433420, 0x00204736}},
{{0x80000005, 0}, Leaf{0xFF40FF18, 0xFF40FF30, 0x10040140, 0x60030140}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "AuthenticAMD");
EXPECT_EQ(info.family, 0x15);
EXPECT_EQ(info.model, 0x38);
EXPECT_EQ(info.stepping, 0x01);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::AMD_BULLDOZER);
char brand_string[49];
FillX86BrandString(brand_string);
EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt
TEST_F(CpuidX86Test, Nehalem) {
// Pre AVX cpus don't have xsave
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
#if defined(CPU_FEATURES_OS_WINDOWS)
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_SSE3_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor :
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
{{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
{{0x00000004, 0}, Leaf{0x1C004122, 0x00C0003F, 0x0000007F, 0x00000000}},
{{0x00000004, 0}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
{{0x00000004, 0}, Leaf{0x1C03C163, 0x03C0003F, 0x00000FFF, 0x00000002}},
{{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00021120}},
{{0x00000006, 0}, Leaf{0x00000001, 0x00000002, 0x00000001, 0x00000000}},
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x0000000A, 0}, Leaf{0x07300403, 0x00000000, 0x00000000, 0x00000603}},
{{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
{{0x0000000B, 0}, Leaf{0x00000004, 0x00000002, 0x00000201, 0x00000000}},
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x28100000}},
{{0x80000002, 0}, Leaf{0x756E6547, 0x20656E69, 0x65746E49, 0x2952286C}},
{{0x80000003, 0}, Leaf{0x55504320, 0x20202020, 0x20202020, 0x40202020}},
{{0x80000004, 0}, Leaf{0x30303020, 0x20402030, 0x37382E31, 0x007A4847}},
{{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x01006040, 0x00000000}},
{{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
{{0x80000008, 0}, Leaf{0x00003028, 0x00000000, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x1A);
EXPECT_EQ(info.stepping, 0x02);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM);
char brand_string[49];
FillX86BrandString(brand_string);
EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU @ 0000 @ 1.87GHz");
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
TEST_F(CpuidX86Test, Atom) {
// Pre AVX cpus don't have xsave
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
#if defined(CPU_FEATURES_OS_WINDOWS)
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI64_INSTRUCTIONS_AVAILABLE);
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_SSE3_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1");
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
{{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x00000004, 0}, Leaf{0x1C000121, 0x0140003F, 0x0000003F, 0x00000001}},
{{0x00000004, 1}, Leaf{0x1C000122, 0x01C0003F, 0x0000003F, 0x00000001}},
{{0x00000004, 2}, Leaf{0x1C00C143, 0x03C0003F, 0x000003FF, 0x00000001}},
{{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x33000020}},
{{0x00000006, 0}, Leaf{0x00000005, 0x00000002, 0x00000009, 0x00000000}},
{{0x00000007, 0}, Leaf{0x00000000, 0x00002282, 0x00000000, 0x00000000}},
{{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x0000000A, 0}, Leaf{0x07280203, 0x00000000, 0x00000000, 0x00004503}},
{{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
{{0x0000000B, 1}, Leaf{0x00000004, 0x00000004, 0x00000201, 0x00000000}},
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000101, 0x28100000}},
{{0x80000002, 0}, Leaf{0x20202020, 0x6E492020, 0x286C6574, 0x43202952}},
{{0x80000003, 0}, Leaf{0x72656C65, 0x52286E6F, 0x50432029, 0x4A202055}},
{{0x80000004, 0}, Leaf{0x30303931, 0x20402020, 0x39392E31, 0x007A4847}},
{{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
{{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x04008040, 0x00000000}},
{{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
{{0x80000008, 0}, Leaf{0x00003024, 0x00000000, 0x00000000, 0x00000000}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x37);
EXPECT_EQ(info.stepping, 0x03);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_ATOM_SMT);
char brand_string[49];
FillX86BrandString(brand_string);
EXPECT_STREQ(brand_string, " Intel(R) Celeron(R) CPU J1900 @ 1.99GHz");
EXPECT_TRUE(info.features.sse);
EXPECT_TRUE(info.features.sse2);
EXPECT_TRUE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_TRUE(info.features.ssse3);
EXPECT_TRUE(info.features.sse4_1);
EXPECT_TRUE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt
TEST_F(CpuidX86Test, P3) {
// Pre AVX cpus don't have xsave
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
#if defined(CPU_FEATURES_OS_WINDOWS)
g_fake_cpu->SetWindowsIsProcessorFeaturePresent(
PF_XMMI_INSTRUCTIONS_AVAILABLE);
#endif // CPU_FEATURES_OS_WINDOWS
#if defined(CPU_FEATURES_OS_DARWIN)
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
#endif // CPU_FEATURES_OS_DARWIN
#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse
)");
#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
{{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x4CECC782, 0x00006778}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x07);
EXPECT_EQ(info.stepping, 0x03);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN);
char brand_string[49];
FillX86BrandString(brand_string);
EXPECT_STREQ(brand_string, "");
EXPECT_TRUE(info.features.mmx);
EXPECT_TRUE(info.features.sse);
EXPECT_FALSE(info.features.sse2);
EXPECT_FALSE(info.features.sse3);
#ifndef CPU_FEATURES_OS_WINDOWS
// Currently disabled on Windows as IsProcessorFeaturePresent do not support
// feature detection > sse3.
EXPECT_FALSE(info.features.ssse3);
EXPECT_FALSE(info.features.sse4_1);
EXPECT_FALSE(info.features.sse4_2);
#endif // CPU_FEATURES_OS_WINDOWS
}
// TODO(user): test what happens when xsave/osxsave are not present.
// TODO(user): test what happens when xmm/ymm/zmm os support are not
// present.
} // namespace
} // namespace cpu_features

View File

@ -0,0 +1,103 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "filesystem_for_testing.h"
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstring>
#include <utility>
namespace cpu_features {
FakeFile::FakeFile(int file_descriptor, const char* content)
: file_descriptor_(file_descriptor), content_(content) {}
FakeFile::~FakeFile() { assert(!opened_); }
void FakeFile::Open() {
assert(!opened_);
opened_ = true;
}
void FakeFile::Close() {
assert(opened_);
opened_ = false;
}
int FakeFile::Read(int fd, void* buf, size_t count) {
assert(count < INT_MAX);
assert(fd == file_descriptor_);
const size_t remainder = content_.size() - head_index_;
const size_t read = count > remainder ? remainder : count;
memcpy(buf, content_.data() + head_index_, read);
head_index_ += read;
assert(read < INT_MAX);
return (int)read;
}
void FakeFilesystem::Reset() { files_.clear(); }
FakeFile* FakeFilesystem::CreateFile(const std::string& filename,
const char* content) {
auto& file = files_[filename];
file =
std::unique_ptr<FakeFile>(new FakeFile(next_file_descriptor_++, content));
return file.get();
}
FakeFile* FakeFilesystem::FindFileOrNull(const std::string& filename) const {
const auto itr = files_.find(filename);
return itr == files_.end() ? nullptr : itr->second.get();
}
FakeFile* FakeFilesystem::FindFileOrDie(const int file_descriptor) const {
for (const auto& filename_file_pair : files_) {
FakeFile* const file_ptr = filename_file_pair.second.get();
if (file_ptr->GetFileDescriptor() == file_descriptor) {
return file_ptr;
}
}
assert(false);
return nullptr;
}
static FakeFilesystem* kFilesystem = new FakeFilesystem();
FakeFilesystem& GetEmptyFilesystem() {
kFilesystem->Reset();
return *kFilesystem;
}
extern "C" int CpuFeatures_OpenFile(const char* filename) {
auto* const file = kFilesystem->FindFileOrNull(filename);
if (file) {
file->Open();
return file->GetFileDescriptor();
}
return -1;
}
extern "C" void CpuFeatures_CloseFile(int file_descriptor) {
kFilesystem->FindFileOrDie(file_descriptor)->Close();
}
extern "C" int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
size_t buffer_size) {
return kFilesystem->FindFileOrDie(file_descriptor)
->Read(file_descriptor, buffer, buffer_size);
}
} // namespace cpu_features

View File

@ -0,0 +1,61 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Implements a fake filesystem, useful for tests.
#ifndef CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
#define CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
#include <memory>
#include <string>
#include <unordered_map>
#include "internal/filesystem.h"
namespace cpu_features {
class FakeFile {
public:
explicit FakeFile(int file_descriptor, const char* content);
~FakeFile();
void Open();
void Close();
int Read(int fd, void* buf, size_t count);
int GetFileDescriptor() const { return file_descriptor_; }
private:
const int file_descriptor_;
const std::string content_;
bool opened_ = false;
size_t head_index_ = 0;
};
class FakeFilesystem {
public:
void Reset();
FakeFile* CreateFile(const std::string& filename, const char* content);
FakeFile* FindFileOrDie(const int file_descriptor) const;
FakeFile* FindFileOrNull(const std::string& filename) const;
private:
int next_file_descriptor_ = 0;
std::unordered_map<std::string, std::unique_ptr<FakeFile>> files_;
};
FakeFilesystem& GetEmptyFilesystem();
} // namespace cpu_features
#endif // CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_

46
cpu_features/test/hwcaps_for_testing.cc vendored Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hwcaps_for_testing.h"
#include <string.h>
#include "internal/string_view.h"
namespace cpu_features {
namespace {
static auto* const g_hardware_capabilities = new HardwareCapabilities();
static auto* const g_platform_types = new PlatformType();
} // namespace
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) {
g_hardware_capabilities->hwcaps = hwcaps;
g_hardware_capabilities->hwcaps2 = hwcaps2;
}
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
return *g_hardware_capabilities;
}
void SetPlatformTypes(const char* platform, const char* base_platform) {
CpuFeatures_StringView_CopyString(str(platform), g_platform_types->platform,
sizeof(g_platform_types->platform));
CpuFeatures_StringView_CopyString(str(base_platform),
g_platform_types->base_platform,
sizeof(g_platform_types->base_platform));
}
PlatformType CpuFeatures_GetPlatformType(void) { return *g_platform_types; }
} // namespace cpu_features

27
cpu_features/test/hwcaps_for_testing.h vendored Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
#define CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
#include "internal/hwcaps.h"
namespace cpu_features {
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2);
void SetPlatformTypes(const char *platform, const char *base_platform);
} // namespace cpu_features
#endif // CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_

View File

@ -0,0 +1,132 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/stack_line_reader.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
namespace cpu_features {
bool operator==(const StringView& a, const StringView& b) {
return CpuFeatures_StringView_IsEquals(a, b);
}
namespace {
std::string ToString(StringView view) { return {view.ptr, view.size}; }
TEST(StackLineReaderTest, Empty) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", "");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str(""));
}
}
TEST(StackLineReaderTest, ManySmallLines) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", "a\nb\nc");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("a"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("b"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("c"));
}
}
TEST(StackLineReaderTest, TruncatedLine) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", R"(First
Second
More than 16 characters, this will be truncated.
last)");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("First"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("Second"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("More than 16 cha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("last"));
}
}
TEST(StackLineReaderTest, TruncatedLines) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", R"(More than 16 characters
Another line that is too long)");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("More than 16 cha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("Another line tha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str(""));
}
}
} // namespace
} // namespace cpu_features

192
cpu_features/test/string_view_test.cc vendored Normal file
View File

@ -0,0 +1,192 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/string_view.h"
#include "gtest/gtest.h"
namespace cpu_features {
bool operator==(const StringView& a, const StringView& b) {
return CpuFeatures_StringView_IsEquals(a, b);
}
namespace {
TEST(StringViewTest, Empty) {
EXPECT_EQ(kEmptyStringView.ptr, nullptr);
EXPECT_EQ(kEmptyStringView.size, 0);
}
TEST(StringViewTest, Build) {
const auto view = str("test");
EXPECT_EQ(view.ptr[0], 't');
EXPECT_EQ(view.size, 4);
}
TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0);
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
// Empty.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(kEmptyStringView, 'z'), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
// Empty.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(kEmptyStringView, str("aa")), -1);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("aa"), kEmptyStringView), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_StartsWith) {
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
EXPECT_FALSE(
CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
EXPECT_FALSE(
CpuFeatures_StringView_StartsWith(kEmptyStringView, str("test")));
}
TEST(StringViewTest, CpuFeatures_StringView_IsEquals) {
EXPECT_TRUE(
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
}
TEST(StringViewTest, CpuFeatures_StringView_PopFront) {
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 2), str("st"));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 0), str("test"));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 4), str(""));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
}
TEST(StringViewTest, CpuFeatures_StringView_PopBack) {
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te"));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test"));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str(""));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str(""));
}
TEST(StringViewTest, CpuFeatures_StringView_KeepFront) {
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te"));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str(""));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test"));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test"));
}
TEST(StringViewTest, CpuFeatures_StringView_Front) {
EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a');
EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a');
}
TEST(StringViewTest, CpuFeatures_StringView_Back) {
EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e');
EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a');
}
TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) {
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
str("first middle last"));
}
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) {
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_CopyString) {
char buf[4];
buf[0] = 'X';
// Empty
CpuFeatures_StringView_CopyString(str(""), buf, sizeof(buf));
EXPECT_STREQ(buf, "");
// Less
CpuFeatures_StringView_CopyString(str("a"), buf, sizeof(buf));
EXPECT_STREQ(buf, "a");
// exact
CpuFeatures_StringView_CopyString(str("abc"), buf, sizeof(buf));
EXPECT_STREQ(buf, "abc");
// More
CpuFeatures_StringView_CopyString(str("abcd"), buf, sizeof(buf));
EXPECT_STREQ(buf, "abc");
}
TEST(StringViewTest, CpuFeatures_StringView_HasWord) {
// Find flags at beginning, middle and end.
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first middle last"), "first"));
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first middle last"), "middle"));
EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last"));
// Do not match partial flags
EXPECT_FALSE(
CpuFeatures_StringView_HasWord(str("first middle last"), "irst"));
EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid"));
EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las"));
}
TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) {
const StringView line = str(" key : first middle last ");
StringView key, value;
EXPECT_TRUE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
EXPECT_EQ(key, str("key"));
EXPECT_EQ(value, str("first middle last"));
}
TEST(StringViewTest, FailingGetAttributeKeyValue) {
const StringView line = str("key first middle last");
StringView key, value;
EXPECT_FALSE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
}
} // namespace
} // namespace cpu_features

554
crc.c Normal file
View File

@ -0,0 +1,554 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// crc.h: Mode S CRC calculation and error correction.
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dump1090.h"
#include <assert.h>
// Errorinfo for "no errors"
static struct errorinfo NO_ERRORS;
// Generator polynomial for the Mode S CRC:
#define MODES_GENERATOR_POLY 0xfff409U
// CRC values for all single-byte messages;
// used to speed up CRC calculation.
static uint32_t crc_table[256];
// Syndrome values for all single-bit errors;
// used to speed up construction of error-
// correction tables.
static uint32_t single_bit_syndrome[112];
static void initLookupTables()
{
int i;
uint8_t msg[112/8];
for (i = 0; i < 256; ++i) {
uint32_t c = i << 16;
int j;
for (j = 0; j < 8; ++j) {
if (c & 0x800000)
c = (c<<1) ^ MODES_GENERATOR_POLY;
else
c = (c<<1);
}
crc_table[i] = c & 0x00ffffff;
}
memset(msg, 0, sizeof(msg));
for (i = 0; i < 112; ++i) {
msg[i/8] ^= 1 << (7 - (i & 7));
single_bit_syndrome[i] = modesChecksum(msg, 112);
msg[i/8] ^= 1 << (7 - (i & 7));
}
}
uint32_t modesChecksum(const uint8_t *message, int bits)
{
uint32_t rem = 0;
int i;
int n = bits/8;
assert(bits % 8 == 0);
assert(n >= 3);
for (i = 0; i < n-3; ++i) {
rem = (rem << 8) ^ crc_table[message[i] ^ ((rem & 0xff0000) >> 16)];
rem = rem & 0xffffff;
}
rem = rem ^ (message[n-3] << 16) ^ (message[n-2] << 8) ^ (message[n-1]);
return rem;
}
static struct errorinfo *bitErrorTable_short;
static int bitErrorTableSize_short;
static struct errorinfo *bitErrorTable_long;
static int bitErrorTableSize_long;
// compare two errorinfo structures
static int syndrome_compare(const void *x, const void *y) {
struct errorinfo *ex = (struct errorinfo*)x;
struct errorinfo *ey = (struct errorinfo*)y;
return (int)ex->syndrome - (int)ey->syndrome;
}
// (n k), the number of ways of selecting k distinct items from a set of n items
static int combinations(int n, int k)
{
int result = 1, i;
if (k == 0 || k == n)
return 1;
if (k > n)
return 0;
for (i = 1; i <= k; ++i) {
result = result * n / i;
n = n - 1;
}
return result;
}
// Recursively populates an errorinfo table with error syndromes
//
// in:
// table: the table to fill
// n: first entry to fill
// maxSize: max size of table
// offset: start bit offset for checksum calculation
// startbit: first bit to introduce errors into
// endbit: (one past) last bit to introduce errors info
// base_entry: template entry to start from
// error_bit: how many error bits have already been set
// max_errors: maximum total error bits to set
// out:
// returns: the next free entry in the table
// table: has been populated between [n, return value)
static int prepareSubtable(struct errorinfo *table, int n, int maxsize, int offset, int startbit, int endbit, struct errorinfo *base_entry, int error_bit, int max_errors)
{
int i = 0;
if (error_bit >= max_errors)
return n;
for (i = startbit; i < endbit; ++i) {
assert(n < maxsize);
table[n] = *base_entry;
table[n].syndrome ^= single_bit_syndrome[i + offset];
table[n].errors = error_bit+1;
table[n].bit[error_bit] = i;
++n;
n = prepareSubtable(table, n, maxsize, offset, i + 1, endbit, &table[n-1], error_bit + 1, max_errors);
}
return n;
}
static int flagCollisions(struct errorinfo *table, int tablesize, int offset, int startbit, int endbit, uint32_t base_syndrome, int error_bit, int first_error, int last_error)
{
int i = 0;
int count = 0;
if (error_bit > last_error)
return 0;
for (i = startbit; i < endbit; ++i) {
struct errorinfo ei;
ei.syndrome = base_syndrome ^ single_bit_syndrome[i + offset];
if (error_bit >= first_error) {
struct errorinfo *collision = bsearch(&ei, table, tablesize, sizeof(struct errorinfo), syndrome_compare);
if (collision != NULL && collision->errors != -1) {
++count;
collision->errors = -1;
}
}
count += flagCollisions(table, tablesize, offset, i+1, endbit, ei.syndrome, error_bit + 1, first_error, last_error);
}
return count;
}
// Allocate and build an error table for messages of length "bits" (max 112)
// returns a pointer to the new table and sets *size_out to the table length
static struct errorinfo *prepareErrorTable(int bits, int max_correct, int max_detect, int *size_out)
{
int maxsize, usedsize;
struct errorinfo *table;
struct errorinfo base_entry;
int i, j;
assert (bits >= 0 && bits <= 112);
assert (max_correct >=0 && max_correct <= MODES_MAX_BITERRORS);
assert (max_detect >= max_correct);
if (!max_correct) {
*size_out = 0;
return NULL;
}
maxsize = 0;
for (i = 1; i <= max_correct; ++i) {
maxsize += combinations(bits, i); // space needed for all i-bit errors
}
#ifdef CRCDEBUG
fprintf(stderr, "Preparing syndrome table to correct up to %d-bit errors (detecting %d-bit errors) in a %d-bit message (max %d entries)\n", max_correct, max_detect, bits, maxsize);
#endif
table = malloc(maxsize * sizeof(struct errorinfo));
base_entry.syndrome = 0;
base_entry.errors = 0;
for (i = 0; i < MODES_MAX_BITERRORS; ++i)
base_entry.bit[i] = -1;
usedsize = prepareSubtable(table, 0, maxsize, 112 - bits, 0, bits, &base_entry, 0, max_correct);
#ifdef CRCDEBUG
fprintf(stderr, "%d syndromes (expected %d).\n", usedsize, maxsize);
fprintf(stderr, "Sorting syndromes..\n");
#endif
qsort(table, usedsize, sizeof(struct errorinfo), syndrome_compare);
#ifdef CRCDEBUG
{
// Show the table stats
fprintf(stderr, "Undetectable errors:\n");
for (i = 1; i <= max_correct; ++i) {
int j, count;
count = 0;
for (j = 0; j < usedsize; ++j)
if (table[j].errors == i && table[j].syndrome == 0)
++count;
fprintf(stderr, " %d undetectable %d-bit errors\n", count, i);
}
}
#endif
// Handle ambiguous cases, where there is more than one possible error pattern
// that produces a given syndrome (this happens with >2 bit errors).
#ifdef CRCDEBUG
fprintf(stderr, "Finding collisions..\n");
#endif
for (i = 0, j = 0; i < usedsize; ++i) {
if (i < usedsize-1 && table[i+1].syndrome == table[i].syndrome) {
// skip over this entry and all collisions
while (i < usedsize && table[i+1].syndrome == table[i].syndrome)
++i;
// now table[i] is the last duplicate
continue;
}
if (i != j)
table[j] = table[i];
++j;
}
if (j < usedsize) {
#ifdef CRCDEBUG
fprintf(stderr, "Discarded %d collisions.\n", usedsize - j);
#endif
usedsize = j;
}
// Flag collisions we want to detect but not correct
if (max_detect > max_correct) {
int flagged;
#ifdef CRCDEBUG
fprintf(stderr, "Flagging collisions between %d - %d bits..\n", max_correct+1, max_detect);
#endif
flagged = flagCollisions(table, usedsize, 112 - bits, 0, bits, 0, 1, max_correct+1, max_detect);
#ifdef CRCDEBUG
fprintf(stderr, "Flagged %d collisions for removal.\n", flagged);
#else
#endif
if (flagged > 0) {
for (i = 0, j = 0; i < usedsize; ++i) {
if (table[i].errors != -1) {
if (i != j)
table[j] = table[i];
++j;
}
}
#ifdef CRCDEBUG
fprintf(stderr, "Discarded %d flagged collisions.\n", usedsize - j);
#endif
usedsize = j;
}
}
if (usedsize < maxsize) {
#ifdef CRCDEBUG
fprintf(stderr, "Shrinking table from %d to %d..\n", maxsize, usedsize);
table = realloc(table, usedsize * sizeof(struct errorinfo));
#endif
}
*size_out = usedsize;
#ifdef CRCDEBUG
{
// Check the table.
unsigned char *msg = malloc(bits/8);
for (i = 0; i < usedsize; ++i) {
int j;
struct errorinfo *ei;
uint32_t result;
memset(msg, 0, bits/8);
ei = &table[i];
for (j = 0; j < ei->errors; ++j) {
msg[ei->bit[j] >> 3] ^= 1 << (7 - (ei->bit[j]&7));
}
result = modesChecksum(msg, bits);
if (result != ei->syndrome) {
fprintf(stderr, "PROBLEM: entry %6d/%6d syndrome %06x errors %d bits ", i, usedsize, ei->syndrome, ei->errors);
for (j = 0; j < ei->errors; ++j)
fprintf(stderr, "%3d ", ei->bit[j]);
fprintf(stderr, " checksum %06x\n", result);
}
}
free(msg);
// Show the table stats
fprintf(stderr, "Syndrome table summary:\n");
for (i = 1; i <= max_correct; ++i) {
int j, count, possible;
count = 0;
for (j = 0; j < usedsize; ++j)
if (table[j].errors == i)
++count;
possible = combinations(bits, i);
fprintf(stderr, " %d entries for %d-bit errors (%d possible, %d%% coverage)\n", count, i, possible, 100 * count / possible);
}
fprintf(stderr, " %d entries total\n", usedsize);
}
#endif
return table;
}
// Precompute syndrome tables for 56- and 112-bit messages.
void modesChecksumInit(int fixBits)
{
initLookupTables();
switch (fixBits) {
case 0:
bitErrorTable_short = bitErrorTable_long = NULL;
bitErrorTableSize_short = bitErrorTableSize_long = 0;
break;
case 1:
// For 1 bit correction, we have 100% coverage up to 4 bit detection, so don't bother
// with flagging collisions there.
bitErrorTable_short = prepareErrorTable(MODES_SHORT_MSG_BITS, 1, 1, &bitErrorTableSize_short);
bitErrorTable_long = prepareErrorTable(MODES_LONG_MSG_BITS, 1, 1, &bitErrorTableSize_long);
break;
default:
// Detect out to 4 bit errors; this reduces our 2-bit coverage to about 65%.
// This can take a little while - tell the user.
fprintf(stderr, "Preparing error correction tables.. ");
bitErrorTable_short = prepareErrorTable(MODES_SHORT_MSG_BITS, 2, 4, &bitErrorTableSize_short);
bitErrorTable_long = prepareErrorTable(MODES_LONG_MSG_BITS, 2, 4, &bitErrorTableSize_long);
fprintf(stderr, "done.\n");
break;
}
}
// Given an error syndrome and message length, return
// an error-correction descriptor, or NULL if the
// syndrome is uncorrectable
struct errorinfo *modesChecksumDiagnose(uint32_t syndrome, int bitlen)
{
struct errorinfo *table;
int tablesize;
struct errorinfo ei;
if (syndrome == 0)
return &NO_ERRORS;
assert (bitlen == 56 || bitlen == 112);
if (bitlen == 56) { table = bitErrorTable_short; tablesize = bitErrorTableSize_short; }
else { table = bitErrorTable_long; tablesize = bitErrorTableSize_long; }
if (!table)
return NULL;
ei.syndrome = syndrome;
return bsearch(&ei, table, tablesize, sizeof(struct errorinfo), syndrome_compare);
}
// Given a message and an error-correction descriptor,
// apply the error correction to the given message.
void modesChecksumFix(uint8_t *msg, struct errorinfo *info)
{
int i;
if (!info)
return;
for (i = 0; i < info->errors; ++i)
msg[info->bit[i] >> 3] ^= 1 << (7 - (info->bit[i] & 7));
}
#ifdef CRCDEBUG
int main(int argc, char **argv)
{
int shortlen, longlen;
int i;
struct errorinfo *shorttable, *longtable;
if (argc < 3) {
fprintf(stderr, "syntax: crctests <ncorrect> <ndetect>\n");
return 1;
}
initLookupTables();
shorttable = prepareErrorTable(MODES_SHORT_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &shortlen);
longtable = prepareErrorTable(MODES_LONG_MSG_BITS, atoi(argv[1]), atoi(argv[2]), &longlen);
// check for DF11 correction syndromes where there is a syndrome with lower 7 bits all zero
// (which would be used for DF11 error correction), but there's also a syndrome which has
// the same upper 17 bits but nonzero lower 7 bits.
// empirically, with ncorrect=1 ndetect=2 we get no ambiguous syndromes;
// for ncorrect=2 ndetect=4 we get 11 ambiguous syndromes:
/*
syndrome 1 = 000C00 bits=[ 44 45 ]
syndrome 2 = 000C1B bits=[ 30 43 ]
syndrome 1 = 001400 bits=[ 43 45 ]
syndrome 2 = 00141B bits=[ 30 44 ]
syndrome 1 = 001800 bits=[ 43 44 ]
syndrome 2 = 00181B bits=[ 30 45 ]
syndrome 1 = 001800 bits=[ 43 44 ]
syndrome 2 = 001836 bits=[ 29 42 ]
syndrome 1 = 002400 bits=[ 42 45 ]
syndrome 2 = 00242D bits=[ 29 30 ]
syndrome 1 = 002800 bits=[ 42 44 ]
syndrome 2 = 002836 bits=[ 29 43 ]
syndrome 1 = 003000 bits=[ 42 43 ]
syndrome 2 = 003036 bits=[ 29 44 ]
syndrome 1 = 003000 bits=[ 42 43 ]
syndrome 2 = 00306C bits=[ 28 41 ]
syndrome 1 = 004800 bits=[ 41 44 ]
syndrome 2 = 00485A bits=[ 28 29 ]
syndrome 1 = 005000 bits=[ 41 43 ]
syndrome 2 = 00506C bits=[ 28 42 ]
syndrome 1 = 006000 bits=[ 41 42 ]
syndrome 2 = 00606C bits=[ 28 43 ]
*/
// So in the DF11 correction logic, we just discard messages that require more than a 1 bit fix.
fprintf(stderr, "checking %d syndromes for DF11 collisions..\n", shortlen);
for (i = 0; i < shortlen; ++i) {
if ((shorttable[i].syndrome & 0xFF) == 0) {
int j;
// all syndromes with the same first 17 bits should sort immediately after entry i,
// so this is fairly easy
for (j = i+1; j < shortlen; ++j) {
if ((shorttable[i].syndrome & 0xFFFF80) == (shorttable[j].syndrome & 0xFFFF80)) {
int k;
int mismatch = 0;
// we don't care if the only differences are in bits that lie in the checksum
for (k = 0; k < shorttable[i].errors; ++k) {
int l, matched = 0;
if (shorttable[i].bit[k] >= 49)
continue; // bit is in the final 7 bits, we don't care
for (l = 0; l < shorttable[j].errors; ++l) {
if (shorttable[i].bit[k] == shorttable[j].bit[l]) {
matched = 1;
break;
}
}
if (!matched)
mismatch = 1;
}
for (k = 0; k < shorttable[j].errors; ++k) {
int l, matched = 0;
if (shorttable[j].bit[k] >= 49)
continue; // bit is in the final 7 bits, we don't care
for (l = 0; l < shorttable[i].errors; ++l) {
if (shorttable[j].bit[k] == shorttable[i].bit[l]) {
matched = 1;
break;
}
}
if (!matched)
mismatch = 1;
}
if (mismatch) {
fprintf(stderr,
"DF11 correction collision: \n"
" syndrome 1 = %06X bits=[",
shorttable[i].syndrome);
for (k = 0; k < shorttable[i].errors; ++k)
fprintf(stderr, " %d", shorttable[i].bit[k]);
fprintf(stderr, " ]\n");
fprintf(stderr,
" syndrome 2 = %06X bits=[",
shorttable[j].syndrome);
for (k = 0; k < shorttable[j].errors; ++k)
fprintf(stderr, " %d", shorttable[j].bit[k]);
fprintf(stderr, " ]\n");
}
} else {
break;
}
}
}
}
free(shorttable);
free(longtable);
return 0;
}
#endif

39
crc.h Normal file
View File

@ -0,0 +1,39 @@
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
//
// crc.h: Mode S checksum prototypes.
//
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
//
// This file is free software: you may copy, redistribute and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation, either version 2 of the License, or (at your
// option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef DUMP1090_CRC_H
#define DUMP1090_CRC_H
#include <stdint.h>
// Global max for fixable bit erros
#define MODES_MAX_BITERRORS 2
struct errorinfo {
uint32_t syndrome; // CRC syndrome
int errors; // number of errors
int8_t bit[MODES_MAX_BITERRORS]; // bit positions to fix (-1 = no bit)
};
void modesChecksumInit(int fixBits);
uint32_t modesChecksum(const uint8_t *msg, int bitlen);
struct errorinfo *modesChecksumDiagnose(uint32_t syndrome, int bitlen);
void modesChecksumFix(uint8_t *msg, struct errorinfo *info);
#endif

30
debian-stretch/control Normal file
View File

@ -0,0 +1,30 @@
Source: dump1090-fa
Section: embedded
Priority: extra
Maintainer: Oliver Jowett <oliver.jowett@flightaware.com>
Build-Depends: debhelper(>=10), librtlsdr-dev, libusb-1.0-0-dev, pkg-config, libncurses5-dev, libbladerf-dev
Standards-Version: 3.9.3
Homepage: http://www.flightaware.com/
Vcs-Git: https://github.com/flightaware/dump1090.git
Package: dump1090
Architecture: all
Depends: dump1090-fa, ${misc:Depends}
Priority: extra
Section: oldlibs
Description: transitional dummy package for dump1090
This is a transitional dummy package to handle upgrades from
the old package name of "dump1090" to the new package name of
"dump1090-fa". It can safely be removed.
Package: dump1090-fa
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libbladerf1 (>= 0.2016.06), adduser, lighttpd
Replaces: dump1090 (<< 3.0)
Breaks: dump1090 (<< 3.0)
Description: ADS-B Ground Station System for RTL-SDR
Networked Aviation Mode S / ADS-B decoder/translator with RTL-SDR software
defined radio USB device support.
.
This is FlightAware's fork of dump1090-mutability, customized for use
in the PiAware sdcard images.

35
debian-stretch/rules Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/default.mk
override_dh_auto_build:
# starch's gcc doesn't support the compiler flags needed for ARM-specific starch flavors;
# turn off runtime CPU detection
dh_auto_build -- RTLSDR=yes BLADERF=yes HACKRF=no LIMESDR=no DUMP1090_VERSION=$(DEB_VERSION) CPUFEATURES=no
override_dh_install:
dh_install
install -d debian/dump1090-fa/usr/bin
cp -a dump1090 debian/dump1090-fa/usr/bin/dump1090-fa
cp -a view1090 debian/dump1090-fa/usr/bin/view1090-fa
override_dh_installinit:
dh_installinit --no-stop-on-upgrade --no-restart-after-upgrade
override_dh_systemd_start:
dh_systemd_start --no-stop-on-upgrade --no-restart-after-upgrade --name=dump1090-fa.service
%:
dh $@ --with=systemd

18
debian/README.librtlsdr vendored Normal file
View File

@ -0,0 +1,18 @@
This package includes binaries that are statically linked against librtlsdr,
which is licensed under the GPL:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The upstream source is available at https://github.com/steve-m/librtlsdr

Some files were not shown because too many files have changed in this diff Show More